6 Commits

Author SHA1 Message Date
DingliZhang fc509b4659 Detect EnableVectorSupport via AlignVector
OpenJDK GHA Sanity Checks / Prepare the run (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-nopch (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-zero (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-minimal (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-hs-optimized (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-x64-static-libs (push) Has been cancelled
OpenJDK GHA Sanity Checks / linux-cross-compile (push) Has been cancelled
OpenJDK GHA Sanity Checks / alpine-linux-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / macos-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-x64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / windows-aarch64 (push) Has been cancelled
OpenJDK GHA Sanity Checks / docs (push) Has been cancelled
2025-09-29 13:07:01 +08:00
Fei Yang a80ee07555 Fix 2025-09-29 10:53:27 +08:00
Fei Yang 444bfc3557 Macro names 2025-09-29 10:31:35 +08:00
Fei Yang 45cbcd9e5c More white spaces 2025-09-26 16:03:01 +08:00
Fei Yang 1912cdfedc White spaces 2025-09-26 15:45:44 +08:00
Fei Yang 077a3ba378 8368732: RISC-V: Detect support for misaligned vector access via hwprobe 2025-09-26 15:35:48 +08:00
1400 changed files with 18908 additions and 35529 deletions
+6 -6
View File
@@ -327,8 +327,8 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-x64
runs-on: 'macos-15-intel'
xcode-toolset-version: '16.4'
runs-on: 'macos-13'
xcode-toolset-version: '14.3.1'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
@@ -340,8 +340,8 @@ jobs:
uses: ./.github/workflows/build-macos.yml
with:
platform: macos-aarch64
runs-on: 'macos-15'
xcode-toolset-version: '16.4'
runs-on: 'macos-14'
xcode-toolset-version: '15.4'
configure-arguments: ${{ github.event.inputs.configure-arguments }}
make-arguments: ${{ github.event.inputs.make-arguments }}
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
@@ -432,9 +432,9 @@ jobs:
with:
platform: macos-aarch64
bootjdk-platform: macos-aarch64
runs-on: macos-15
runs-on: macos-14
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
xcode-toolset-version: '16.4'
xcode-toolset-version: '15.4'
debug-suffix: -debug
test-windows-x64:
+1 -1
View File
@@ -450,7 +450,7 @@ itself (<code>-timeoutFactor</code>). Also, some test cases that
programmatically wait a certain amount of time will apply this factor.
If we run in forced compilation mode (<code>-Xcomp</code>), the build
system will automatically adjust this factor to compensate for less
performance. Defaults to 4.</p>
performance. Defaults to 1.</p>
<h4 id="failure_handler_timeout">FAILURE_HANDLER_TIMEOUT</h4>
<p>Sets the argument <code>-timeoutHandlerTimeout</code> for JTReg. The
default value is 0. This is only valid if the failure handler is
+1 -1
View File
@@ -387,7 +387,7 @@ The `TIMEOUT_FACTOR` is forwarded to JTReg framework itself
(`-timeoutFactor`). Also, some test cases that programmatically wait a
certain amount of time will apply this factor. If we run in forced
compilation mode (`-Xcomp`), the build system will automatically
adjust this factor to compensate for less performance. Defaults to 4.
adjust this factor to compensate for less performance. Defaults to 1.
#### FAILURE_HANDLER_TIMEOUT
+2 -2
View File
@@ -946,8 +946,8 @@ define SetupRunJtregTestBody
JTREG_ALL_OPTIONS := $$(JTREG_JAVA_OPTIONS) $$(JTREG_VM_OPTIONS)
JTREG_AUTO_PROBLEM_LISTS :=
# Please reach consensus before changing this.
JTREG_AUTO_TIMEOUT_FACTOR := 4
# Please reach consensus before changing this. It was not easy changing it to a `1`.
JTREG_AUTO_TIMEOUT_FACTOR := 1
ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), )
JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt
-3
View File
@@ -116,9 +116,6 @@ else ifeq ($(call isTargetOs, aix), true)
$(eval STATIC_LIB_EXPORT_FILES += $(lib).exp) \
)
STATIC_LIBS := -Wl,-bexpfull $(STATIC_LIB_FILES) $(addprefix -Wl$(COMMA)-bE:, $(STATIC_LIB_EXPORT_FILES))
ifeq ($(DEBUG_LEVEL), slowdebug)
STATIC_LIBS += -Wl,-bbigtoc
endif
else
$(error Unsupported platform)
endif
+1 -1
View File
@@ -363,7 +363,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_COMPLEX_TOOLS],
# Check if it's a GNU date compatible version
AC_MSG_CHECKING([if date is a GNU compatible version])
check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox\|uutils"`
check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox"`
if test "x$check_date" != x; then
AC_MSG_RESULT([yes])
IS_GNU_DATE=yes
+28 -2
View File
@@ -408,6 +408,27 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK],
AC_MSG_CHECKING([if Boot JDK is 32 or 64 bits])
AC_MSG_RESULT([$BOOT_JDK_BITS])
# Try to enable CDS
AC_MSG_CHECKING([for local Boot JDK Class Data Sharing (CDS)])
BOOT_JDK_CDS_ARCHIVE=$CONFIGURESUPPORT_OUTPUTDIR/classes.jsa
UTIL_ADD_JVM_ARG_IF_OK([-XX:+UnlockDiagnosticVMOptions -XX:-VerifySharedSpaces -XX:SharedArchiveFile=$BOOT_JDK_CDS_ARCHIVE],boot_jdk_cds_args,[$JAVA])
if test "x$boot_jdk_cds_args" != x; then
# Try creating a CDS archive
$JAVA $boot_jdk_cds_args -Xshare:dump > /dev/null 2>&1
if test $? -eq 0; then
BOOTJDK_USE_LOCAL_CDS=true
AC_MSG_RESULT([yes, created])
else
# Generation failed, don't use CDS.
BOOTJDK_USE_LOCAL_CDS=false
AC_MSG_RESULT([no, creation failed])
fi
else
BOOTJDK_USE_LOCAL_CDS=false
AC_MSG_RESULT([no, -XX:SharedArchiveFile not supported])
fi
BOOTJDK_SETUP_CLASSPATH
])
@@ -423,8 +444,13 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS],
# Force en-US environment
UTIL_ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA])
UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=off:stdout],boot_jdk_jvmargs,[$JAVA])
UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=warning:stderr],boot_jdk_jvmargs,[$JAVA])
if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then
# Use our own CDS archive
UTIL_ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA])
else
# Otherwise optimistically use the system-wide one, if one is present
UTIL_ADD_JVM_ARG_IF_OK([-Xshare:auto],boot_jdk_jvmargs,[$JAVA])
fi
# Finally append user provided options to allow them to override.
UTIL_ADD_JVM_ARG_IF_OK([$USER_BOOT_JDK_OPTIONS],boot_jdk_jvmargs,[$JAVA])
@@ -44,3 +44,7 @@ JAVAC_CMD := $(FIXPATH) $(BOOT_JDK)/bin/javac
JAR_CMD := $(FIXPATH) $(BOOT_JDK)/bin/jar
# The bootcycle JVM arguments may differ from the original boot jdk.
JAVA_FLAGS_BIG := @BOOTCYCLE_JVM_ARGS_BIG@
# Any CDS settings generated for the bootjdk are invalid in the bootcycle build.
# By filtering out those JVM args, the bootcycle JVM will use its default
# settings for CDS.
JAVA_FLAGS := $(filter-out -XX:SharedArchiveFile% -Xshare%, $(JAVA_FLAGS))
+1 -1
View File
@@ -79,7 +79,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
fi
if test "x$OPENJDK_TARGET_OS" = xaix; then
BASIC_LDFLAGS="-Wl,-b64 -Wl,-brtl -Wl,-bnorwexec -Wl,-blibpath:/usr/lib:lib -Wl,-bnoexpall \
-Wl,-bernotok -Wl,-bcdtors:mbr::s -Wl,-bdatapsize:64k -Wl,-btextpsize:64k -Wl,-bstackpsize:64k"
-Wl,-bernotok -Wl,-bdatapsize:64k -Wl,-btextpsize:64k -Wl,-bstackpsize:64k"
BASIC_LDFLAGS_JVM_ONLY="$BASIC_LDFLAGS_JVM_ONLY -Wl,-lC_r -Wl,-bbigtoc"
fi
+2 -7
View File
@@ -565,14 +565,9 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_UNDEFINED_BEHAVIOR_SANITIZER],
# with an additional define LLVM_SYMBOLIZER, which we set here.
# To calculate the correct llvm_symbolizer path we can use the location of the compiler, because
# their relation is fixed.
# In the ubsan case we have to link every binary with the C++-compiler as linker, because inherently
# the C-Compiler and the C++-compiler used as linker provide a different set of ubsan exports.
# Linking an executable with the C-compiler and one of its shared libraries with the C++-compiler
# leeds to unresolved symbols.
if test "x$TOOLCHAIN_TYPE" = "xclang" && test "x$OPENJDK_TARGET_OS" = "xaix"; then
UBSAN_CFLAGS="$UBSAN_CFLAGS -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
UBSAN_LDFLAGS="$UBSAN_LDFLAGS -Wl,-bbigtoc"
LD="$LDCXX"
UBSAN_CFLAGS="$UBSAN_CFLAGS -fno-sanitize=function,vptr -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
UBSAN_LDFLAGS="$UBSAN_LDFLAGS -fno-sanitize=function,vptr -Wl,-bbigtoc"
fi
UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED,
DESC: [enable UndefinedBehaviorSanitizer],
+1 -1
View File
@@ -28,7 +28,7 @@
################################################################################
# Minimum supported versions
JTREG_MINIMUM_VERSION=8.1
JTREG_MINIMUM_VERSION=8
GTEST_MINIMUM_VERSION=1.14.0
################################################################################
+5 -1
View File
@@ -136,8 +136,12 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBPTHREAD"
fi
# librt - for timers (timer_* functions)
# librt for legacy clock_gettime
if test "x$OPENJDK_TARGET_OS" = xlinux; then
# Hotspot needs to link librt to get the clock_* functions.
# But once our supported minimum build and runtime platform
# has glibc 2.17, this can be removed as the functions are
# in libc.
BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lrt"
fi
+11 -11
View File
@@ -26,24 +26,24 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
GTEST_VERSION=1.14.0
JTREG_VERSION=8.1+1
JTREG_VERSION=8+2
LINUX_X64_BOOT_JDK_EXT=tar.gz
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz
LINUX_X64_BOOT_JDK_SHA256=59cdcaf255add4721de38eb411d4ecfe779356b61fb671aee63c7dec78054c2b
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz
LINUX_X64_BOOT_JDK_SHA256=88b090fa80c6c1d084ec9a755233967458788e2c0777ae2e172230c5c692d7ef
ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz
ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25%2B36/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25_36.tar.gz
ALPINE_LINUX_X64_BOOT_JDK_SHA256=637e47474d411ed86134f413af7d5fef4180ddb0bf556347b7e74a88cf8904c8
ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin24-binaries/releases/download/jdk-24%2B36/OpenJDK24U-jdk_x64_alpine-linux_hotspot_24_36.tar.gz
ALPINE_LINUX_X64_BOOT_JDK_SHA256=a642608f0da78344ee6812fb1490b8bc1d7ad5a18064c70994d6f330568c51cb
MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-aarch64_bin.tar.gz
MACOS_AARCH64_BOOT_JDK_SHA256=2006337bf326fdfdf6117081751ba38c1c8706d63419ecac7ff102ff7c776876
MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-aarch64_bin.tar.gz
MACOS_AARCH64_BOOT_JDK_SHA256=f7133238a12714a62c5ad2bd4da6741130be1a82512065da9ca23dee26b2d3d3
MACOS_X64_BOOT_JDK_EXT=tar.gz
MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-x64_bin.tar.gz
MACOS_X64_BOOT_JDK_SHA256=47482ad9888991ecac9b2bcc131e2b53ff78aff275104cef85f66252308e8a09
MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-x64_bin.tar.gz
MACOS_X64_BOOT_JDK_SHA256=6bbfb1d01741cbe55ab90299cb91464b695de9a3ace85c15131aa2f50292f321
WINDOWS_X64_BOOT_JDK_EXT=zip
WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_windows-x64_bin.zip
WINDOWS_X64_BOOT_JDK_SHA256=85bcc178461e2cb3c549ab9ca9dfa73afd54c09a175d6510d0884071867137d3
WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip
WINDOWS_X64_BOOT_JDK_SHA256=11d1d9f6ac272d5361c8a0bef01894364081c7fb1a6914c2ad2fc312ae83d63b
+5 -5
View File
@@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) {
};
};
common.boot_jdk_version = "25";
common.boot_jdk_build_number = "37";
common.boot_jdk_version = "24";
common.boot_jdk_build_number = "36";
common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-"
+ common.boot_jdk_version
+ (input.build_os == "macosx" ? ".jdk/Contents/Home" : "");
@@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "jpg",
product: "jtreg",
version: "8.1",
build_number: "1",
file: "bundles/jtreg-8.1+1.zip",
version: "8",
build_number: "2",
file: "bundles/jtreg-8+2.zip",
environment_name: "JT_HOME",
environment_path: input.get("jtreg", "home_path") + "/bin",
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
+1 -1
View File
@@ -37,6 +37,6 @@ DEFAULT_VERSION_DATE=2026-03-17
DEFAULT_VERSION_CLASSFILE_MAJOR=70 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26"
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25 26"
DEFAULT_JDK_SOURCE_TARGET_VERSION=26
DEFAULT_PROMOTED_VERSION_PRE=ea
+5
View File
@@ -32,6 +32,11 @@
547d 92ca
53da 9b7e
446e f86f
#
# we should use this one instead of the 4260<-ff0d
#4260 2212
4260 ff0d
#
426A 00A6
43A1 301C
444A 2014
+9 -1
View File
@@ -25,6 +25,13 @@
# 4260 <--> 2212
# 426A <--> 00A6
#
# Warning:
# "our old" implementation seems agree with above "new" mappings
# except the entries 4260 <-> 2212. To keep the "compatbility"
# with the "old" implementation, I changed the entries "temporarily"
# 4260 <-> 2212
# 4260 <- ff0d
#
00 0000
01 0001
02 0002
@@ -400,7 +407,8 @@ FF 009F
425D FF09
425E FF1B
425F FFE2
4260 FF0D
#4260 FF0D
4260 2212
4261 FF0F
426A FFE4
426B FF0C
+26 -26
View File
@@ -1,5 +1,5 @@
#
# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -57,61 +57,61 @@
COMMA := ,
OS := $(shell uname -o)
CPU := $(shell uname -m)
os := $(shell uname -o)
cpu := $(shell uname -p)
# Figure out what platform this is building on.
ME := $(CPU)-$(if $(findstring Linux,$(OS)),linux-gnu)
me := $(cpu)-$(if $(findstring Linux,$(os)),linux-gnu)
$(info Building on platform $(ME))
$(info Building on platform $(me))
#
# By default just build for the current platform, which is assumed to be Linux
#
ifeq ($(TARGETS), )
PLATFORMS := $(ME)
HOST_PLATFORMS := $(PLATFORMS)
platforms := $(me)
host_platforms := $(platforms)
else
PLATFORMS := $(subst $(COMMA), , $(TARGETS))
HOST_PLATFORMS := $(ME)
platforms := $(subst $(COMMA), , $(TARGETS))
host_platforms := $(me)
endif
TARGET_PLATFORMS := $(PLATFORMS)
$(info HOST_PLATFORMS $(HOST_PLATFORMS))
$(info TARGET_PLATFORMS $(TARGET_PLATFORMS))
target_platforms := $(platforms)
$(info host_platforms $(host_platforms))
$(info target_platforms $(target_platforms))
all compile : $(PLATFORMS)
all compile : $(platforms)
ifeq ($(SKIP_ME), )
$(foreach p,$(filter-out $(ME),$(PLATFORMS)),$(eval $(p) : $$(ME)))
$(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me)))
endif
OUTPUT_ROOT = $(abspath ../../build/devkit)
RESULT = $(OUTPUT_ROOT)/result
SUBMAKEVARS = HOST=$@ BUILD=$(ME) RESULT=$(RESULT) OUTPUT_ROOT=$(OUTPUT_ROOT)
submakevars = HOST=$@ BUILD=$(me) RESULT=$(RESULT) OUTPUT_ROOT=$(OUTPUT_ROOT)
$(HOST_PLATFORMS) :
$(host_platforms) :
@echo 'Building compilers for $@'
@echo 'Targets: $(TARGET_PLATFORMS)'
for p in $(filter $@, $(TARGET_PLATFORMS)) $(filter-out $@, $(TARGET_PLATFORMS)); do \
$(MAKE) -f Tools.gmk download-rpms $(SUBMAKEVARS) \
@echo 'Targets: $(target_platforms)'
for p in $(filter $@, $(target_platforms)) $(filter-out $@, $(target_platforms)); do \
$(MAKE) -f Tools.gmk download-rpms $(submakevars) \
TARGET=$$p PREFIX=$(RESULT)/$@-to-$$p && \
$(MAKE) -f Tools.gmk all $(SUBMAKEVARS) \
$(MAKE) -f Tools.gmk all $(submakevars) \
TARGET=$$p PREFIX=$(RESULT)/$@-to-$$p && \
$(MAKE) -f Tools.gmk ccache $(SUBMAKEVARS) \
$(MAKE) -f Tools.gmk ccache $(submakevars) \
TARGET=$@ PREFIX=$(RESULT)/$@-to-$$p || exit 1 ; \
done
@echo 'All done"'
TODAY := $(shell date +%Y%m%d)
today := $(shell date +%Y%m%d)
define Mktar
$(1)-to-$(2)_tar = $$(RESULT)/sdk-$(1)-to-$(2)-$$(TODAY).tar.gz
$(1)-to-$(2)_tar = $$(RESULT)/sdk-$(1)-to-$(2)-$$(today).tar.gz
$$($(1)-to-$(2)_tar) : PLATFORM = $(1)-to-$(2)
TARFILES += $$($(1)-to-$(2)_tar)
endef
$(foreach p,$(HOST_PLATFORMS),$(foreach t,$(TARGET_PLATFORMS),$(eval $(call Mktar,$(p),$(t)))))
$(foreach p,$(host_platforms),$(foreach t,$(target_platforms),$(eval $(call Mktar,$(p),$(t)))))
tars : all $(TARFILES)
onlytars : $(TARFILES)
@@ -119,9 +119,9 @@ onlytars : $(TARFILES)
$(MAKE) -r -f Tars.gmk SRC_DIR=$(RESULT)/$(PLATFORM) TAR_FILE=$@
clean :
rm -rf $(addprefix ../../build/devkit/, result $(HOST_PLATFORMS))
rm -rf $(addprefix ../../build/devkit/, result $(host_platforms))
dist-clean: clean
rm -rf $(addprefix ../../build/devkit/, src download)
FORCE :
.PHONY : all compile tars $(HOST_PLATFORMS) clean dist-clean
.PHONY : all compile tars $(configs) $(host_platforms) clean dist-clean
+78 -109
View File
@@ -39,7 +39,7 @@
# Fix this...
#
lowercase = $(shell echo $1 | tr A-Z a-z)
uppercase = $(shell echo $1 | tr a-z A-Z)
$(info TARGET=$(TARGET))
$(info HOST=$(HOST))
@@ -104,48 +104,26 @@ endif
################################################################################
# Define external dependencies
GNU_BASE_URL := https://ftp.gnu.org/pub/gnu
BINUTILS_VER_ONLY := 2.43
BINUTILS_BASE_URL := $(GNU_BASE_URL)/binutils
BINUTILS_SHA512 := 93e063163e54d6a6ee2bd48dc754270bf757a3635b49a702ed6b310e929e94063958512d191e66beaf44275f7ea60865dbde138b624626739679fcc306b133bb
CCACHE_VER_ONLY := 4.10.2
CCACHE_BASE_URL := https://github.com/ccache/ccache/releases/download
gcc_ver_only := 14.2.0
binutils_ver_only := 2.43
ccache_ver_only := 4.10.2
CCACHE_CMAKE_BASED := 1
CCACHE_SHA512 := 3815c71d7266c32839acb306763268018acc58b3bbbd9ec79fc101e4217c1720d2ad2f01645bf69168c1c61d27700b6f3bb755cfa82689cca69824f015653f3c
mpfr_ver_only := 4.2.1
gmp_ver_only := 6.3.0
mpc_ver_only := 1.3.1
gdb_ver_only := 15.2
GCC_VER_ONLY := 14.2.0
GCC_BASE_URL := $(GNU_BASE_URL)/gcc
GCC_SHA512 := 932bdef0cda94bacedf452ab17f103c0cb511ff2cec55e9112fc0328cbf1d803b42595728ea7b200e0a057c03e85626f937012e49a7515bc5dd256b2bf4bc396
dependencies := gcc binutils ccache mpfr gmp mpc gdb
GDB_VER_ONLY := 15.2
GDB_BASE_URL := $(GNU_BASE_URL)/gdb
GDB_SHA512 := 624007deceb5b15ba89c0725883d1a699fa46714ef30887f3d0165e17c5d65d634671740a135aa69e437d916218abb08cfa2a38ed309ff19d48f51da56b2a8ba
$(foreach dep,$(dependencies),$(eval $(dep)_ver := $(dep)-$($(dep)_ver_only)))
GMP_VER_ONLY := 6.3.0
GMP_BASE_URL := $(GNU_BASE_URL)/gmp
GMP_SHA512 := e85a0dab5195889948a3462189f0e0598d331d3457612e2d3350799dba2e244316d256f8161df5219538eb003e4b5343f989aaa00f96321559063ed8c8f29fd2
MPC_VER_ONLY := 1.3.1
MPC_BASE_URL := $(GNU_BASE_URL)/mpc
MPC_SHA512 := 4bab4ef6076f8c5dfdc99d810b51108ced61ea2942ba0c1c932d624360a5473df20d32b300fc76f2ba4aa2a97e1f275c9fd494a1ba9f07c4cb2ad7ceaeb1ae97
MPFR_VER_ONLY := 4.2.1
MPFR_BASE_URL := https://www.mpfr.org
MPFR_SHA512 := bc68c0d755d5446403644833ecbb07e37360beca45f474297b5d5c40926df1efc3e2067eecffdf253f946288bcca39ca89b0613f545d46a9e767d1d4cf358475
DEPENDENCIES := BINUTILS CCACHE GCC GDB GMP MPC MPFR
$(foreach dep,$(DEPENDENCIES),$(eval $(dep)_VER := $(call lowercase,$(dep)-$($(dep)_VER_ONLY))))
BINUTILS_URL := $(BINUTILS_BASE_URL)/$(BINUTILS_VER).tar.xz
CCACHE_URL := $(CCACHE_BASE_URL)/v$(CCACHE_VER_ONLY)/$(CCACHE_VER).tar.xz
GCC_URL := $(GCC_BASE_URL)/$(GCC_VER)/$(GCC_VER).tar.xz
GDB_URL := $(GDB_BASE_URL)/$(GDB_VER).tar.xz
GMP_URL := $(GMP_BASE_URL)/$(GMP_VER).tar.xz
MPC_URL := $(MPC_BASE_URL)/$(MPC_VER).tar.gz
MPFR_URL := $(MPFR_BASE_URL)/$(MPFR_VER)/$(MPFR_VER).tar.xz
GCC := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz
BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz
CCACHE := https://github.com/ccache/ccache/releases/download/v$(ccache_ver_only)/$(ccache_ver).tar.xz
MPFR := https://www.mpfr.org/$(mpfr_ver)/$(mpfr_ver).tar.bz2
GMP := http://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2
MPC := http://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz
GDB := http://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz
REQUIRED_MIN_MAKE_MAJOR_VERSION := 4
ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),)
@@ -202,10 +180,10 @@ DOWNLOAD_RPMS := $(DOWNLOAD)/rpms/$(TARGET)-$(LINUX_VERSION)
SRCDIR := $(OUTPUT_ROOT)/src
# Marker file for unpacking rpms
RPMS := $(SYSROOT)/rpms_unpacked
rpms := $(SYSROOT)/rpms_unpacked
# Need to patch libs that are linker scripts to use non-absolute paths
LIBS := $(SYSROOT)/libs_patched
libs := $(SYSROOT)/libs_patched
################################################################################
# Download RPMs
@@ -220,10 +198,10 @@ download-rpms:
################################################################################
# Unpack source packages
# Generate downloading + checksum verification of sources.
define DownloadVerify
# Generate downloading + unpacking of sources.
define Download
# Allow override
$(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)_URL))))
$(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)))))
$(1)_DIR = $(abspath $(SRCDIR)/$$($(1)_DIRNAME))
ifeq ($$($(1)_CMAKE_BASED),)
$(1)_CFG = $$($(1)_DIR)/configure
@@ -234,7 +212,7 @@ define DownloadVerify
$(1)_SRC_MARKER = $$($(1)_DIR)/CMakeLists.txt
$(1)_CONFIG = $$(CMAKE_CONFIG) $$($(1)_DIR)
endif
$(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)_URL))
$(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)))
$$($(1)_SRC_MARKER) : $$($(1)_FILE)
mkdir -p $$(SRCDIR)
@@ -246,20 +224,11 @@ define DownloadVerify
touch $$@
$$($(1)_FILE) :
mkdir -p $$(@D)
wget -O - $$($(1)_URL) > $$@.tmp
sha512_actual="$$$$(sha512sum $$@.tmp | awk '{ print $$$$1; }')"; \
if [ x"$$$${sha512_actual}" != x"$$($(1)_SHA512)" ]; then \
echo "Checksum mismatch for $$@.tmp"; \
echo " Expected: $$($(1)_SHA512)"; \
echo " Actual: $$$${sha512_actual}"; \
exit 1; \
fi
mv $$@.tmp $$@
wget -P $(DOWNLOAD) $$($(1))
endef
# Download and unpack all source packages
$(foreach dep,$(DEPENDENCIES),$(eval $(call DownloadVerify,$(dep))))
$(foreach dep,$(dependencies),$(eval $(call Download,$(call uppercase,$(dep)))))
################################################################################
# Unpack RPMS
@@ -281,7 +250,7 @@ RPM_FILE_LIST := $(sort $(foreach a, $(RPM_ARCHS), \
# Note. For building linux you should install rpm2cpio.
define unrpm
$(SYSROOT)/$(notdir $(1)).unpacked : $(1)
$$(RPMS) : $(SYSROOT)/$(notdir $(1)).unpacked
$$(rpms) : $(SYSROOT)/$(notdir $(1)).unpacked
endef
%.unpacked :
@@ -308,7 +277,7 @@ $(foreach p,$(RPM_FILE_LIST),$(eval $(call unrpm,$(p))))
# have it anyway, but just to make sure...
# Patch libc.so and libpthread.so to force linking against libraries in sysroot
# and not the ones installed on the build machine.
$(LIBS) : $(RPMS)
$(libs) : $(rpms)
@echo Patching libc and pthreads
@(for f in `find $(SYSROOT) -name libc.so -o -name libpthread.so`; do \
(cat $$f | sed -e 's|/usr/lib64/||g' \
@@ -324,10 +293,10 @@ $(LIBS) : $(RPMS)
# Create links for ffi header files so that they become visible by default when using the
# devkit.
ifeq ($(ARCH), x86_64)
$(SYSROOT)/usr/include/ffi.h: $(RPMS)
$(SYSROOT)/usr/include/ffi.h: $(rpms)
cd $(@D) && rm -f $(@F) && ln -s ../lib/libffi-*/include/$(@F) .
$(SYSROOT)/usr/include/ffitarget.h: $(RPMS)
$(SYSROOT)/usr/include/ffitarget.h: $(rpms)
cd $(@D) && rm -f $(@F) && ln -s ../lib/libffi-*/include/$(@F) .
SYSROOT_LINKS += $(SYSROOT)/usr/include/ffi.h $(SYSROOT)/usr/include/ffitarget.h
@@ -336,7 +305,7 @@ endif
################################################################################
# Define marker files for each source package to be compiled
$(foreach dep,$(DEPENDENCIES),$(eval $(dep) = $(TARGETDIR)/$($(dep)_VER).done))
$(foreach dep,$(dependencies),$(eval $(dep) = $(TARGETDIR)/$($(dep)_ver).done))
################################################################################
@@ -376,48 +345,48 @@ TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-)
# CFLAG_<name> to most likely -m32.
define mk_bfd
$$(info Libs for $(1))
$$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile \
$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
: CFLAGS += $$(CFLAGS_$(1))
$$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile \
$$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \
: LIBDIRS = --libdir=$(TARGETDIR)/$(1)
BFDLIB += $$(TARGETDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1)).done
BFDMAKES += $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile
bfdlib += $$(TARGETDIR)/$$(binutils_ver)-$(subst /,-,$(1)).done
bfdmakes += $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile
endef
# Create one set of bfds etc for each multilib arch
$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l))))
# Only build these two libs.
$(BFDLIB) : MAKECMD = all-libiberty all-bfd
$(BFDLIB) : INSTALLCMD = install-libiberty install-bfd
$(bfdlib) : MAKECMD = all-libiberty all-bfd
$(bfdlib) : INSTALLCMD = install-libiberty install-bfd
# Building targets libbfd + libiberty. HOST==TARGET, i.e not
# for a cross env.
$(BFDMAKES) : CONFIG = --target=$(TARGET) \
$(bfdmakes) : CONFIG = --target=$(TARGET) \
--host=$(TARGET) --build=$(BUILD) \
--prefix=$(TARGETDIR) \
--with-sysroot=$(SYSROOT) \
$(LIBDIRS)
$(BFDMAKES) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-)
$(bfdmakes) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-)
################################################################################
$(GCC) \
$(BINUTILS) \
$(GMP) \
$(MPFR) \
$(MPC) \
$(BFDMAKES) \
$(CCACHE) : ENVS += $(TOOLS)
$(gcc) \
$(binutils) \
$(gmp) \
$(mpfr) \
$(mpc) \
$(bfdmakes) \
$(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))
$(BUILDDIR)/$(binutils_ver)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS))
ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), )
# gold compiles but cannot link properly on s390x @ gcc 13.2 and Fedore 41
@@ -428,8 +397,8 @@ endif
# Makefile creation. Simply run configure in build dir.
# Setting CFLAGS to -O2 generates a much faster ld.
$(BFDMAKES) \
$(BUILDDIR)/$(BINUTILS_VER)/Makefile \
$(bfdmakes) \
$(BUILDDIR)/$(binutils_ver)/Makefile \
: $(BINUTILS_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
@mkdir -p $(@D)
@@ -448,7 +417,7 @@ $(BUILDDIR)/$(BINUTILS_VER)/Makefile \
) > $(@D)/log.config 2>&1
@echo 'done'
$(BUILDDIR)/$(MPFR_VER)/Makefile \
$(BUILDDIR)/$(mpfr_ver)/Makefile \
: $(MPFR_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
@mkdir -p $(@D)
@@ -463,7 +432,7 @@ $(BUILDDIR)/$(MPFR_VER)/Makefile \
) > $(@D)/log.config 2>&1
@echo 'done'
$(BUILDDIR)/$(GMP_VER)/Makefile \
$(BUILDDIR)/$(gmp_ver)/Makefile \
: $(GMP_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
@mkdir -p $(@D)
@@ -480,7 +449,7 @@ $(BUILDDIR)/$(GMP_VER)/Makefile \
) > $(@D)/log.config 2>&1
@echo 'done'
$(BUILDDIR)/$(MPC_VER)/Makefile \
$(BUILDDIR)/$(mpc_ver)/Makefile \
: $(MPC_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
@mkdir -p $(@D)
@@ -499,11 +468,11 @@ $(BUILDDIR)/$(MPC_VER)/Makefile \
# Only valid if glibc target -> linux
# proper destructor handling for c++
ifneq (,$(findstring linux,$(TARGET)))
$(BUILDDIR)/$(GCC_VER)/Makefile : CONFIG += --enable-__cxa_atexit
$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit
endif
ifeq ($(ARCH), armhfp)
$(BUILDDIR)/$(GCC_VER)/Makefile : CONFIG += --with-float=hard
$(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard
endif
ifneq ($(filter riscv64 ppc64le s390x, $(ARCH)), )
@@ -518,7 +487,7 @@ endif
# skip native language.
# and link and assemble with the binutils we created
# earlier, so --with-gnu*
$(BUILDDIR)/$(GCC_VER)/Makefile \
$(BUILDDIR)/$(gcc_ver)/Makefile \
: $(GCC_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
mkdir -p $(@D)
@@ -540,17 +509,17 @@ $(BUILDDIR)/$(GCC_VER)/Makefile \
@echo 'done'
# need binutils for gcc
$(GCC) : $(BINUTILS)
$(gcc) : $(binutils)
# as of 4.3 or so need these for doing config
$(BUILDDIR)/$(GCC_VER)/Makefile : $(GMP) $(MPFR) $(MPC)
$(MPFR) : $(GMP)
$(MPC) : $(GMP) $(MPFR)
$(BUILDDIR)/$(gcc_ver)/Makefile : $(gmp) $(mpfr) $(mpc)
$(mpfr) : $(gmp)
$(mpc) : $(gmp) $(mpfr)
################################################################################
# Build gdb but only where host and target match
ifeq ($(HOST), $(TARGET))
$(BUILDDIR)/$(GDB_VER)/Makefile: $(GDB_CFG)
$(BUILDDIR)/$(gdb_ver)/Makefile: $(GDB_CFG)
$(info Configuring $@. Log in $(@D)/log.config)
mkdir -p $(@D)
( \
@@ -563,9 +532,9 @@ ifeq ($(HOST), $(TARGET))
) > $(@D)/log.config 2>&1
@echo 'done'
$(GDB): $(GCC)
$(gdb): $(gcc)
else
$(BUILDDIR)/$(GDB_VER)/Makefile:
$(BUILDDIR)/$(gdb_ver)/Makefile:
$(info Faking $@, not used when cross-compiling)
mkdir -p $(@D)
echo "install:" > $@
@@ -574,7 +543,7 @@ endif
################################################################################
# very straightforward. just build a ccache. it is only for host.
$(BUILDDIR)/$(CCACHE_VER)/Makefile \
$(BUILDDIR)/$(ccache_ver)/Makefile \
: $(CCACHE_SRC_MARKER)
$(info Configuring $@. Log in $(@D)/log.config)
@mkdir -p $(@D)
@@ -585,12 +554,12 @@ $(BUILDDIR)/$(CCACHE_VER)/Makefile \
) > $(@D)/log.config 2>&1
@echo 'done'
GCC_PATCHED = $(TARGETDIR)/gcc-patched
gccpatch = $(TARGETDIR)/gcc-patched
################################################################################
# For some reason cpp is not created as a target-compiler
ifeq ($(HOST),$(TARGET))
$(GCC_PATCHED) : $(GCC) link_libs
$(gccpatch) : $(gcc) link_libs
@echo -n 'Creating compiler symlinks...'
@for f in cpp; do \
if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ]; \
@@ -618,7 +587,7 @@ ifeq ($(HOST),$(TARGET))
done;)
@echo 'done'
else
$(GCC_PATCHED) :
$(gccpatch) :
@echo 'done'
endif
@@ -646,7 +615,7 @@ $(PREFIX)/devkit.info:
echo '# This file describes to configure how to interpret the contents of this' >> $@
echo '# devkit' >> $@
echo '' >> $@
echo 'DEVKIT_NAME="$(GCC_VER) - $(LINUX_VERSION)"' >> $@
echo 'DEVKIT_NAME="$(gcc_ver) - $(LINUX_VERSION)"' >> $@
echo 'DEVKIT_TOOLCHAIN_PATH="$$DEVKIT_ROOT/bin"' >> $@
echo 'DEVKIT_SYSROOT="$$DEVKIT_ROOT/$(TARGET)/sysroot"' >> $@
echo 'DEVKIT_EXTRA_PATH="$$DEVKIT_ROOT/bin"' >> $@
@@ -682,32 +651,32 @@ ifeq ($(TARGET), $(HOST))
@echo 'Creating missing $* soft link'
ln -s $(TARGET)-$* $@
MISSING_LINKS := $(addprefix $(PREFIX)/bin/, \
addr2line ar as c++ c++filt dwp elfedit g++ gcc gcc-$(GCC_VER_ONLY) gprof ld ld.bfd \
missing-links := $(addprefix $(PREFIX)/bin/, \
addr2line ar as c++ c++filt dwp elfedit g++ gcc gcc-$(gcc_ver_only) gprof ld ld.bfd \
ld.gold nm objcopy objdump ranlib readelf size strings strip)
endif
# Add link to work around "plugin needed to handle lto object" (JDK-8344272)
$(PREFIX)/lib/bfd-plugins/liblto_plugin.so: $(PREFIX)/libexec/gcc/$(TARGET)/$(GCC_VER_ONLY)/liblto_plugin.so
$(PREFIX)/lib/bfd-plugins/liblto_plugin.so: $(PREFIX)/libexec/gcc/$(TARGET)/$(gcc_ver_only)/liblto_plugin.so
@echo 'Creating missing $(@F) soft link'
@mkdir -p $(@D)
ln -s $$(realpath -s --relative-to=$(@D) $<) $@
MISSING_LINKS += $(PREFIX)/lib/bfd-plugins/liblto_plugin.so
missing-links += $(PREFIX)/lib/bfd-plugins/liblto_plugin.so
################################################################################
bfdlib : $(BFDLIB)
binutils : $(BINUTILS)
rpms : $(RPMS)
libs : $(LIBS)
bfdlib : $(bfdlib)
binutils : $(binutils)
rpms : $(rpms)
libs : $(libs)
sysroot : rpms libs
gcc : sysroot $(GCC) $(GCC_PATCHED)
gdb : $(GDB)
all : binutils gcc bfdlib $(PREFIX)/devkit.info $(MISSING_LINKS) $(SYSROOT_LINKS) \
gcc : sysroot $(gcc) $(gccpatch)
gdb : $(gdb)
all : binutils gcc bfdlib $(PREFIX)/devkit.info $(missing-links) $(SYSROOT_LINKS) \
$(THESE_MAKEFILES) gdb
# this is only built for host. so separate.
ccache : $(CCACHE)
ccache : $(ccache)
.PHONY : gcc all binutils bfdlib link_libs rpms libs sysroot
+1 -1
View File
@@ -93,7 +93,7 @@ elif test "x$TARGET_PLATFORM" = xlinux_x64; then
rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.x86_64.rpm | cpio -d -i
elif test "x$TARGET_PLATFORM" = xlinux_x86; then
M4_VERSION=1.4.13-5
wget https://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm
wget http://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm
cd $IMAGE_DIR
rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.i686.rpm | cpio -d -i
else
+1
View File
@@ -189,6 +189,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \
DISABLED_WARNINGS_gcc_c1_Runtime1_aarch64.cpp := unused-const-variable, \
DISABLED_WARNINGS_gcc_cgroupV1Subsystem_linux.cpp := address, \
DISABLED_WARNINGS_gcc_cgroupV2Subsystem_linux.cpp := address, \
DISABLED_WARNINGS_gcc_g1FreeIdSet.cpp := unused-const-variable, \
DISABLED_WARNINGS_gcc_handshake.cpp := stringop-overflow, \
DISABLED_WARNINGS_gcc_interp_masm_x86.cpp := uninitialized, \
DISABLED_WARNINGS_gcc_javaClasses.cpp := unused-const-variable, \
@@ -22,7 +22,6 @@
// Java extension
"jdk.project.jdkhome": "{{OUTPUTDIR}}/jdk",
"jdk.java.onSave.organizeImports": false, // prevents unnecessary changes
"jdk.serverVmOptions": ["-Xmx2G"], // prevent out of memory
// Additional conventions
"files.associations": {
+2
View File
@@ -27,5 +27,7 @@
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
COPY += .js
CLEAN += .properties
################################################################################
+39
View File
@@ -0,0 +1,39 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
################################################################################
include LauncherCommon.gmk
################################################################################
## Build jrunscript
################################################################################
$(eval $(call SetupBuildLauncher, jrunscript, \
MAIN_CLASS := com.sun.tools.script.shell.Main, \
JAVA_ARGS := --add-modules ALL-DEFAULT, \
))
################################################################################
+19 -15
View File
@@ -1267,38 +1267,38 @@ source %{
// registers conditionally reserved.
_ANY_REG32_mask = _ALL_REG32_mask;
_ANY_REG32_mask.remove(OptoReg::as_OptoReg(r31_sp->as_VMReg()));
_ANY_REG32_mask.Remove(OptoReg::as_OptoReg(r31_sp->as_VMReg()));
_ANY_REG_mask = _ALL_REG_mask;
_PTR_REG_mask = _ALL_REG_mask;
_NO_SPECIAL_REG32_mask = _ALL_REG32_mask;
_NO_SPECIAL_REG32_mask.subtract(_NON_ALLOCATABLE_REG32_mask);
_NO_SPECIAL_REG32_mask.SUBTRACT(_NON_ALLOCATABLE_REG32_mask);
_NO_SPECIAL_REG_mask = _ALL_REG_mask;
_NO_SPECIAL_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_PTR_REG_mask = _ALL_REG_mask;
_NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_PTR_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask);
// r27 is not allocatable when compressed oops is on and heapbase is not
// zero, compressed klass pointers doesn't use r27 after JDK-8234794
if (UseCompressedOops && (CompressedOops::base() != nullptr)) {
_NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg()));
}
// r29 is not allocatable when PreserveFramePointer is on
if (PreserveFramePointer) {
_NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
}
_NO_SPECIAL_NO_RFP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask;
_NO_SPECIAL_NO_RFP_PTR_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg()));
_NO_SPECIAL_NO_RFP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg()));
}
// Optimizaton of volatile gets and puts
@@ -1734,7 +1734,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
}
//=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY;
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset
@@ -2520,10 +2520,10 @@ uint Matcher::int_pressure_limit()
// as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip
// derived pointers and lastly fail to spill after reaching maximum
// number of iterations. Lowering the default pressure threshold to
// (_NO_SPECIAL_REG32_mask.size() minus 1) forces CallNode to become
// (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become
// a high register pressure area of the code so that split_DEF can
// generate DefinitionSpillCopy for the derived pointer.
uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.size() - 1;
uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1;
if (!PreserveFramePointer) {
// When PreserveFramePointer is off, frame pointer is allocatable,
// but different from other SOC registers, it is excluded from
@@ -2538,7 +2538,7 @@ uint Matcher::int_pressure_limit()
uint Matcher::float_pressure_limit()
{
// _FLOAT_REG_mask is generated by adlc from the float_reg register class.
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE;
}
bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) {
@@ -2568,6 +2568,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return FP_REG_mask();
}
bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
Node* u = addp->fast_out(i);
+9 -11
View File
@@ -7081,31 +7081,29 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{
%}
instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2,
vReg tmp3, pReg ptmp, pRegGov pgtmp) %{
vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_BYTE);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ptmp, TEMP pgtmp);
match(Set dst (CompressV src pg));
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $ptmp, $pgtmp" %}
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
__ sve_compress_byte($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister,
$ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes);
$tmp1$$FloatRegister,$tmp2$$FloatRegister,
$tmp3$$FloatRegister,$tmp4$$FloatRegister,
$ptmp$$PRegister, $pgtmp$$PRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vcompressS(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, pRegGov pgtmp) %{
instruct vcompressS(vReg dst, vReg src, pReg pg,
vReg tmp1, vReg tmp2, pRegGov pgtmp) %{
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_SHORT);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP pgtmp);
match(Set dst (CompressV src pg));
format %{ "vcompressS $dst, $src, $pg\t# KILL $tmp1, $tmp2, $pgtmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
__ sve_dup($tmp1$$FloatRegister, __ H, 0);
__ sve_compress_short($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister,
length_in_bytes);
$tmp1$$FloatRegister,$tmp2$$FloatRegister, $pgtmp$$PRegister);
%}
ins_pipe(pipe_slow);
%}
+9 -11
View File
@@ -5069,31 +5069,29 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{
%}
instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2,
vReg tmp3, pReg ptmp, pRegGov pgtmp) %{
vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_BYTE);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ptmp, TEMP pgtmp);
match(Set dst (CompressV src pg));
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $ptmp, $pgtmp" %}
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
__ sve_compress_byte($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister,
$ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes);
$tmp1$$FloatRegister,$tmp2$$FloatRegister,
$tmp3$$FloatRegister,$tmp4$$FloatRegister,
$ptmp$$PRegister, $pgtmp$$PRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vcompressS(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, pRegGov pgtmp) %{
instruct vcompressS(vReg dst, vReg src, pReg pg,
vReg tmp1, vReg tmp2, pRegGov pgtmp) %{
predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_SHORT);
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP pgtmp);
match(Set dst (CompressV src pg));
format %{ "vcompressS $dst, $src, $pg\t# KILL $tmp1, $tmp2, $pgtmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
__ sve_dup($tmp1$$FloatRegister, __ H, 0);
__ sve_compress_short($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister,
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister,
length_in_bytes);
$tmp1$$FloatRegister,$tmp2$$FloatRegister, $pgtmp$$PRegister);
%}
ins_pipe(pipe_slow);
%}
@@ -3486,7 +3486,6 @@ public:
INSN(sve_smaxv, 0b00000100, 0b001000001); // signed maximum reduction to scalar
INSN(sve_smin, 0b00000100, 0b001010000); // signed minimum vectors
INSN(sve_sminv, 0b00000100, 0b001010001); // signed minimum reduction to scalar
INSN(sve_splice,0b00000101, 0b101100100); // splice two vectors under predicate control, destructive
INSN(sve_sub, 0b00000100, 0b000001000); // vector sub
INSN(sve_uaddv, 0b00000100, 0b000001001); // unsigned add reduction to scalar
INSN(sve_umax, 0b00000100, 0b001001000); // unsigned maximum vectors
@@ -1,12 +1,11 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -21,23 +20,9 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
// Generated by jextract
#include "interpreter/bytecodes.hpp"
package jdk.internal.ffi.generated.timespec;
import java.lang.foreign.*;
public class timespec_h extends timespec_h$shared {
timespec_h() {
// Should not be called directly
}
static final Arena LIBRARY_ARENA = Arena.ofAuto();
static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup()
.or(Linker.nativeLinker().defaultLookup());
}
@@ -1,12 +1,11 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -21,23 +20,12 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Defines native structures for errno APIs.
* Generated with the following jextract command:
* {@snippet lang = "Shell Script":
*
* HEADER_NAME=errno.h
* echo "#include <errno.h>" > $HEADER_NAME
* echo "#include <string.h>" >> $HEADER_NAME
*
* jextract --target-package jdk.internal.ffi.generated.errno \
* --include-constant EINTR \
* --include-function strerror_r \
* $HEADER_NAME
* }
*
*/
package jdk.internal.ffi.generated.errno;
#ifndef CPU_AARCH64_BYTECODES_AARCH64_HPP
#define CPU_AARCH64_BYTECODES_AARCH64_HPP
// No aarch64 specific bytecodes
#endif // CPU_AARCH64_BYTECODES_AARCH64_HPP
@@ -383,6 +383,13 @@ LIR_Opr FrameMap::stack_pointer() {
return FrameMap::sp_opr;
}
// JSR 292
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
return LIR_OprFact::illegalOpr; // Not needed on aarch64
}
bool FrameMap::validate_frame() {
return true;
}
@@ -2203,117 +2203,114 @@ void C2_MacroAssembler::sve_gen_mask_imm(PRegister dst, BasicType bt, uint32_t l
// Pack active elements of src, under the control of mask, into the lowest-numbered elements of dst.
// Any remaining elements of dst will be filled with zero.
// Clobbers: rscratch1
// Preserves: mask, vzr
// Preserves: src, mask
void C2_MacroAssembler::sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask,
FloatRegister vzr, FloatRegister vtmp,
PRegister pgtmp, unsigned vector_length_in_bytes) {
FloatRegister vtmp1, FloatRegister vtmp2,
PRegister pgtmp) {
assert(pgtmp->is_governing(), "This register has to be a governing predicate register");
// When called by sve_compress_byte, src and vtmp may be the same register.
assert_different_registers(dst, src, vzr);
assert_different_registers(dst, vtmp, vzr);
assert_different_registers(dst, src, vtmp1, vtmp2);
assert_different_registers(mask, pgtmp);
// high <-- low
// Example input: src = hh gg ff ee dd cc bb aa, one character is 8 bits.
// mask = 01 00 00 01 01 00 01 01, one character is 1 bit.
// Expected result: dst = 00 00 00 hh ee dd bb aa
// Example input: src = 8888 7777 6666 5555 4444 3333 2222 1111
// mask = 0001 0000 0000 0001 0001 0000 0001 0001
// Expected result: dst = 0000 0000 0000 8888 5555 4444 2222 1111
sve_dup(vtmp2, H, 0);
// Extend lowest half to type INT.
// dst = 00dd 00cc 00bb 00aa
// dst = 00004444 00003333 00002222 00001111
sve_uunpklo(dst, S, src);
// pgtmp = 0001 0000 0001 0001
// pgtmp = 00000001 00000000 00000001 00000001
sve_punpklo(pgtmp, mask);
// Pack the active elements in size of type INT to the right,
// and fill the remainings with zero.
// dst = 0000 00dd 00bb 00aa
// dst = 00000000 00004444 00002222 00001111
sve_compact(dst, S, dst, pgtmp);
// Narrow the result back to type SHORT.
// dst = 00 00 00 00 00 dd bb aa
sve_uzp1(dst, H, dst, vzr);
// Return if the vector length is no more than MaxVectorSize/2, since the
// highest half is invalid.
if (vector_length_in_bytes <= (MaxVectorSize >> 1)) {
return;
}
// dst = 0000 0000 0000 0000 0000 4444 2222 1111
sve_uzp1(dst, H, dst, vtmp2);
// Count the active elements of lowest half.
// rscratch1 = 3
sve_cntp(rscratch1, S, ptrue, pgtmp);
// Repeat to the highest half.
// pgtmp = 0001 0000 0000 0001
// pgtmp = 00000001 00000000 00000000 00000001
sve_punpkhi(pgtmp, mask);
// vtmp = 00hh 00gg 00ff 00ee
sve_uunpkhi(vtmp, S, src);
// vtmp = 0000 0000 00hh 00ee
sve_compact(vtmp, S, vtmp, pgtmp);
// vtmp = 00 00 00 00 00 00 hh ee
sve_uzp1(vtmp, H, vtmp, vzr);
// vtmp1 = 00008888 00007777 00006666 00005555
sve_uunpkhi(vtmp1, S, src);
// vtmp1 = 00000000 00000000 00008888 00005555
sve_compact(vtmp1, S, vtmp1, pgtmp);
// vtmp1 = 0000 0000 0000 0000 0000 0000 8888 5555
sve_uzp1(vtmp1, H, vtmp1, vtmp2);
// pgtmp = 00 00 00 00 00 01 01 01
sve_whilelt(pgtmp, H, zr, rscratch1);
// Compressed low: dst = 00 00 00 00 00 dd bb aa
// Compressed high: vtmp = 00 00 00 00 00 00 hh ee
// Combine the compressed low with the compressed high:
// dst = 00 00 00 hh ee dd bb aa
sve_splice(dst, H, pgtmp, vtmp);
// Compressed low: dst = 0000 0000 0000 0000 0000 4444 2222 1111
// Compressed high: vtmp1 = 0000 0000 0000 0000 0000 0000 8888 5555
// Left shift(cross lane) compressed high with TRUE_CNT lanes,
// TRUE_CNT is the number of active elements in the compressed low.
neg(rscratch1, rscratch1);
// vtmp2 = {4 3 2 1 0 -1 -2 -3}
sve_index(vtmp2, H, rscratch1, 1);
// vtmp1 = 0000 0000 0000 8888 5555 0000 0000 0000
sve_tbl(vtmp1, H, vtmp1, vtmp2);
// Combine the compressed high(after shifted) with the compressed low.
// dst = 0000 0000 0000 8888 5555 4444 2222 1111
sve_orr(dst, dst, vtmp1);
}
// Clobbers: rscratch1, rscratch2
// Preserves: src, mask
void C2_MacroAssembler::sve_compress_byte(FloatRegister dst, FloatRegister src, PRegister mask,
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3,
PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes) {
FloatRegister vtmp1, FloatRegister vtmp2,
FloatRegister vtmp3, FloatRegister vtmp4,
PRegister ptmp, PRegister pgtmp) {
assert(pgtmp->is_governing(), "This register has to be a governing predicate register");
assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3);
assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3, vtmp4);
assert_different_registers(mask, ptmp, pgtmp);
// high <-- low
// Example input: src = q p n m l k j i h g f e d c b a, one character is 8 bits.
// mask = 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 1, one character is 1 bit.
// Expected result: dst = 0 0 0 0 0 0 0 0 0 0 0 p i g c a
FloatRegister vzr = vtmp3;
sve_dup(vzr, B, 0);
// Example input: src = 88 77 66 55 44 33 22 11
// mask = 01 00 00 01 01 00 01 01
// Expected result: dst = 00 00 00 88 55 44 22 11
sve_dup(vtmp4, B, 0);
// Extend lowest half to type SHORT.
// vtmp1 = 0h 0g 0f 0e 0d 0c 0b 0a
// vtmp1 = 0044 0033 0022 0011
sve_uunpklo(vtmp1, H, src);
// ptmp = 00 01 00 00 00 01 00 01
// ptmp = 0001 0000 0001 0001
sve_punpklo(ptmp, mask);
// Pack the active elements in size of type SHORT to the right,
// and fill the remainings with zero.
// dst = 00 00 00 00 00 0g 0c 0a
unsigned extended_size = vector_length_in_bytes << 1;
sve_compress_short(dst, vtmp1, ptmp, vzr, vtmp2, pgtmp, extended_size > MaxVectorSize ? MaxVectorSize : extended_size);
// Narrow the result back to type BYTE.
// dst = 0 0 0 0 0 0 0 0 0 0 0 0 0 g c a
sve_uzp1(dst, B, dst, vzr);
// Return if the vector length is no more than MaxVectorSize/2, since the
// highest half is invalid.
if (vector_length_in_bytes <= (MaxVectorSize >> 1)) {
return;
}
// Count the active elements of lowest half.
// rscratch2 = 3
sve_cntp(rscratch2, H, ptrue, ptmp);
// Pack the active elements in size of type SHORT to the right,
// and fill the remainings with zero.
// dst = 0000 0044 0022 0011
sve_compress_short(dst, vtmp1, ptmp, vtmp2, vtmp3, pgtmp);
// Narrow the result back to type BYTE.
// dst = 00 00 00 00 00 44 22 11
sve_uzp1(dst, B, dst, vtmp4);
// Repeat to the highest half.
// ptmp = 00 01 00 00 00 00 00 01
// ptmp = 0001 0000 0000 0001
sve_punpkhi(ptmp, mask);
// vtmp2 = 0q 0p 0n 0m 0l 0k 0j 0i
// vtmp1 = 0088 0077 0066 0055
sve_uunpkhi(vtmp2, H, src);
// vtmp1 = 00 00 00 00 00 00 0p 0i
sve_compress_short(vtmp1, vtmp2, ptmp, vzr, vtmp2, pgtmp, extended_size - MaxVectorSize);
// vtmp1 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 p i
sve_uzp1(vtmp1, B, vtmp1, vzr);
// vtmp1 = 0000 0000 0088 0055
sve_compress_short(vtmp1, vtmp2, ptmp, vtmp3, vtmp4, pgtmp);
// ptmp = 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
sve_whilelt(ptmp, B, zr, rscratch2);
// Compressed low: dst = 0 0 0 0 0 0 0 0 0 0 0 0 0 g c a
// Compressed high: vtmp1 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 p i
// Combine the compressed low with the compressed high:
// dst = 0 0 0 0 0 0 0 0 0 0 0 p i g c a
sve_splice(dst, B, ptmp, vtmp1);
sve_dup(vtmp4, B, 0);
// vtmp1 = 00 00 00 00 00 00 88 55
sve_uzp1(vtmp1, B, vtmp1, vtmp4);
// Compressed low: dst = 00 00 00 00 00 44 22 11
// Compressed high: vtmp1 = 00 00 00 00 00 00 88 55
// Left shift(cross lane) compressed high with TRUE_CNT lanes,
// TRUE_CNT is the number of active elements in the compressed low.
neg(rscratch2, rscratch2);
// vtmp2 = {4 3 2 1 0 -1 -2 -3}
sve_index(vtmp2, B, rscratch2, 1);
// vtmp1 = 00 00 00 88 55 00 00 00
sve_tbl(vtmp1, B, vtmp1, vtmp2);
// Combine the compressed high(after shifted) with the compressed low.
// dst = 00 00 00 88 55 44 22 11
sve_orr(dst, dst, vtmp1);
}
void C2_MacroAssembler::neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ) {
@@ -173,12 +173,13 @@
// lowest-numbered elements of dst. Any remaining elements of dst will
// be filled with zero.
void sve_compress_byte(FloatRegister dst, FloatRegister src, PRegister mask,
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3,
PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes);
FloatRegister vtmp1, FloatRegister vtmp2,
FloatRegister vtmp3, FloatRegister vtmp4,
PRegister ptmp, PRegister pgtmp);
void sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask,
FloatRegister vzr, FloatRegister vtmp,
PRegister pgtmp, unsigned vector_length_in_bytes);
FloatRegister vtmp1, FloatRegister vtmp2,
PRegister pgtmp);
void neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ);
+44 -1
View File
@@ -228,7 +228,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
nmethod* nm = sender_blob->as_nmethod_or_null();
if (nm != nullptr) {
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
nm->method()->is_method_handle_intrinsic()) {
return false;
}
}
@@ -453,6 +454,48 @@ JavaThread** frame::saved_thread_address(const frame& f) {
return thread_addr;
}
//------------------------------------------------------------------------------
// frame::verify_deopt_original_pc
//
// Verifies the calculated original PC of a deoptimization PC for the
// given unextended SP.
#ifdef ASSERT
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
frame fr;
// This is ugly but it's better than to change {get,set}_original_pc
// to take an SP value as argument. And it's only a debugging
// method anyway.
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
}
#endif
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
#ifdef ASSERT
void frame::adjust_unextended_sp() {
// On aarch64, sites calling method handle intrinsics and lambda forms are treated
// as any other call site. Therefore, no special action is needed when we are
// returning to any of these call sites.
if (_cb != nullptr) {
nmethod* sender_nm = _cb->as_nmethod_or_null();
if (sender_nm != nullptr) {
// If the sender PC is a deoptimization point, get the original PC.
if (sender_nm->is_deopt_entry(_pc) ||
sender_nm->is_deopt_mh_entry(_pc)) {
verify_deopt_original_pc(sender_nm, _unextended_sp);
}
}
}
}
#endif
//------------------------------------------------------------------------------
// frame::sender_for_interpreter_frame
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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.
*
@@ -141,6 +141,8 @@
int _offset_unextended_sp; // for use in stack-chunk frames
};
void adjust_unextended_sp() NOT_DEBUG_RETURN;
// true means _sp value is correct and we can use it to get the sender's sp
// of the compiled frame, otherwise, _sp value may be invalid and we can use
// _fp to get the sender's sp if PreserveFramePointer is enabled.
@@ -150,6 +152,11 @@
return (intptr_t*) addr_at(offset);
}
#ifdef ASSERT
// Used in frame::sender_for_{interpreter,compiled}_frame
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp);
#endif
public:
// Constructors
@@ -116,6 +116,8 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
}
inline void frame::setup(address pc) {
adjust_unextended_sp();
address original_pc = get_deopt_original_pc();
if (original_pc != nullptr) {
_pc = original_pc;
@@ -221,6 +223,7 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
// assert(_pc != nullptr, "no pc?");
_cb = CodeCache::find_blob(_pc);
adjust_unextended_sp();
address original_pc = get_deopt_original_pc();
if (original_pc != nullptr) {
@@ -35,6 +35,8 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
#define SUPPORT_MONITOR_COUNT
// Aarch64 was not originally defined to be multi-copy-atomic, but now
// is. See: "Simplifying ARM Concurrency: Multicopy-atomic Axiomatic
// and Operational Models for ARMv8"
@@ -1704,14 +1704,3 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index
add(cache, cache, Array<ResolvedMethodEntry>::base_offset_in_bytes());
lea(cache, Address(cache, index));
}
#ifdef ASSERT
void InterpreterMacroAssembler::verify_field_offset(Register reg) {
// Verify the field offset is not in the header, implicitly checks for 0
Label L;
subs(zr, reg, oopDesc::base_offset_in_bytes());
br(Assembler::GE, L);
stop("bad field offset");
bind(L);
}
#endif
@@ -319,8 +319,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
void load_resolved_indy_entry(Register cache, Register index);
void load_field_entry(Register cache, Register index, int bcp_offset = 1);
void load_method_entry(Register cache, Register index, int bcp_offset = 1);
void verify_field_offset(Register reg) NOT_DEBUG_RETURN;
};
#endif // CPU_AARCH64_INTERP_MASM_AARCH64_HPP
@@ -39,22 +39,24 @@ public:
// 3 - restoring an old state (javaCalls)
void clear(void) {
// No hardware barriers are necessary. All members are volatile and the profiler
// is run from a signal handler and only observers the thread its running on.
// clearing _last_Java_sp must be first
_last_Java_sp = nullptr;
OrderAccess::release();
_last_Java_fp = nullptr;
_last_Java_pc = nullptr;
}
void copy(JavaFrameAnchor* src) {
// No hardware barriers are necessary. All members are volatile and the profiler
// is run from a signal handler and only observers the thread its running on.
// In order to make sure the transition state is valid for "this"
// We must clear _last_Java_sp before copying the rest of the new data
//
// Hack Alert: Temporary bugfix for 4717480/4721647
// To act like previous version (pd_cache_state) don't null _last_Java_sp
// unless the value is changing
//
if (_last_Java_sp != src->_last_Java_sp) {
_last_Java_sp = nullptr;
OrderAccess::release();
}
_last_Java_fp = src->_last_Java_fp;
_last_Java_pc = src->_last_Java_pc;
@@ -634,13 +634,12 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp,
last_java_sp = esp;
}
str(last_java_sp, Address(rthread, JavaThread::last_Java_sp_offset()));
// last_java_fp is optional
if (last_java_fp->is_valid()) {
str(last_java_fp, Address(rthread, JavaThread::last_Java_fp_offset()));
}
// We must set sp last.
str(last_java_sp, Address(rthread, JavaThread::last_Java_sp_offset()));
}
void MacroAssembler::set_last_Java_frame(Register last_java_sp,
@@ -5631,6 +5630,38 @@ void MacroAssembler::tlab_allocate(Register obj,
bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
}
void MacroAssembler::inc_held_monitor_count(Register tmp) {
Address dst(rthread, JavaThread::held_monitor_count_offset());
#ifdef ASSERT
ldr(tmp, dst);
increment(tmp);
str(tmp, dst);
Label ok;
tbz(tmp, 63, ok);
STOP("assert(held monitor count underflow)");
should_not_reach_here();
bind(ok);
#else
increment(dst);
#endif
}
void MacroAssembler::dec_held_monitor_count(Register tmp) {
Address dst(rthread, JavaThread::held_monitor_count_offset());
#ifdef ASSERT
ldr(tmp, dst);
decrement(tmp);
str(tmp, dst);
Label ok;
tbz(tmp, 63, ok);
STOP("assert(held monitor count underflow)");
should_not_reach_here();
bind(ok);
#else
decrement(dst);
#endif
}
void MacroAssembler::verify_tlab() {
#ifdef ASSERT
if (UseTLAB && VerifyOops) {
@@ -983,6 +983,9 @@ public:
void push_cont_fastpath(Register java_thread = rthread);
void pop_cont_fastpath(Register java_thread = rthread);
void inc_held_monitor_count(Register tmp);
void dec_held_monitor_count(Register tmp);
// Round up to a power of two
void round_to(Register reg, int modulus);
@@ -90,6 +90,7 @@ void Relocation::pd_set_call_destination(address x) {
void trampoline_stub_Relocation::pd_fix_owner_after_move() {
NativeCall* call = nativeCall_at(owner());
assert(call->raw_destination() == owner(), "destination should be empty");
address trampoline = addr();
address dest = nativeCallTrampolineStub_at(trampoline)->destination();
if (!Assembler::reachable_from_branch_at(owner(), dest)) {
@@ -985,8 +985,11 @@ static void fill_continuation_entry(MacroAssembler* masm) {
__ ldr(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset()));
__ str(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
__ ldr(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset()));
__ str(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
__ str(zr, Address(rthread, JavaThread::cont_fastpath_offset()));
__ str(zr, Address(rthread, JavaThread::held_monitor_count_offset()));
}
// on entry, sp points to the ContinuationEntry
@@ -1002,6 +1005,50 @@ static void continuation_enter_cleanup(MacroAssembler* masm) {
#endif
__ ldr(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
__ str(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset()));
if (CheckJNICalls) {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ ldrw(rscratch1, Address(sp, ContinuationEntry::flags_offset()));
__ cbzw(rscratch1, L_skip_vthread_code);
// If the held monitor count is > 0 and this vthread is terminating then
// it failed to release a JNI monitor. So we issue the same log message
// that JavaThread::exit does.
__ ldr(rscratch1, Address(rthread, JavaThread::jni_monitor_count_offset()));
__ cbz(rscratch1, L_skip_vthread_code);
// Save return value potentially containing the exception oop in callee-saved R19.
__ mov(r19, r0);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held));
// Restore potential return value.
__ mov(r0, r19);
// For vthreads we have to explicitly zero the JNI monitor count of the carrier
// on termination. The held count is implicitly zeroed below when we restore from
// the parent held count (which has to be zero).
__ str(zr, Address(rthread, JavaThread::jni_monitor_count_offset()));
__ bind(L_skip_vthread_code);
}
#ifdef ASSERT
else {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ ldrw(rscratch1, Address(sp, ContinuationEntry::flags_offset()));
__ cbzw(rscratch1, L_skip_vthread_code);
// See comment just above. If not checking JNI calls the JNI count is only
// needed for assertion checking.
__ str(zr, Address(rthread, JavaThread::jni_monitor_count_offset()));
__ bind(L_skip_vthread_code);
}
#endif
__ ldr(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
__ str(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset()));
__ ldr(rscratch2, Address(sp, ContinuationEntry::parent_offset()));
__ str(rscratch2, Address(rthread, JavaThread::cont_entry_offset()));
__ add(rfp, sp, (int)ContinuationEntry::size());
@@ -168,7 +168,6 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
Register temp_reg, bool load_bc_into_bc_reg/*=true*/,
int byte_no)
{
assert_different_registers(bc_reg, temp_reg);
if (!RewriteBytecodes) return;
Label L_patch_done;
@@ -232,12 +231,9 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
__ stop("patching the wrong bytecode");
__ bind(L_okay);
#endif
// Patch bytecode with release store to coordinate with ResolvedFieldEntry loads
// in fast bytecode codelets. load_field_entry has a memory barrier that gains
// the needed ordering, together with control dependency on entering the fast codelet
// itself.
__ lea(temp_reg, at_bcp(0));
__ stlrb(bc_reg, temp_reg);
// patch bytecode
__ strb(bc_reg, at_bcp(0));
__ bind(L_patch_done);
}
@@ -2273,7 +2269,7 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
assert_different_registers(Rcache, index, temp);
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
Label L_clinit_barrier_slow, L_done;
Label resolved, clinit_barrier_slow;
Bytecodes::Code code = bytecode();
__ load_method_entry(Rcache, index);
@@ -2288,20 +2284,11 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
// Load-acquire the bytecode to match store-release in InterpreterRuntime
__ ldarb(temp, temp);
__ subs(zr, temp, (int) code); // have we resolved this bytecode?
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
__ br(Assembler::NE, L_clinit_barrier_slow);
__ ldr(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(temp, temp);
__ clinit_barrier(temp, rscratch1, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ br(Assembler::EQ, L_done);
}
__ br(Assembler::EQ, resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
__ bind(clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ mov(temp, (int) code);
__ call_VM(noreg, entry, temp);
@@ -2310,7 +2297,14 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
__ load_method_entry(Rcache, index);
// n.b. unlike x86 Rcache is now rcpool plus the indexed offset
// so all clients ofthis method must be modified accordingly
__ bind(L_done);
__ bind(resolved);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
__ ldr(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(temp, temp);
__ clinit_barrier(temp, rscratch1, nullptr, &clinit_barrier_slow);
}
}
void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
@@ -2319,7 +2313,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
const Register temp = r19;
assert_different_registers(Rcache, index, temp);
Label L_clinit_barrier_slow, L_done;
Label resolved;
Bytecodes::Code code = bytecode();
switch (code) {
@@ -2338,29 +2332,16 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
// Load-acquire the bytecode to match store-release in ResolvedFieldEntry::fill_in()
__ ldarb(temp, temp);
__ subs(zr, temp, (int) code); // have we resolved this bytecode?
// Class initialization barrier for static fields
if (VM_Version::supports_fast_class_init_checks() &&
(bytecode() == Bytecodes::_getstatic || bytecode() == Bytecodes::_putstatic)) {
const Register field_holder = temp;
__ br(Assembler::NE, L_clinit_barrier_slow);
__ ldr(field_holder, Address(Rcache, in_bytes(ResolvedFieldEntry::field_holder_offset())));
__ clinit_barrier(field_holder, rscratch1, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ br(Assembler::EQ, L_done);
}
__ br(Assembler::EQ, resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ mov(temp, (int) code);
__ call_VM(noreg, entry, temp);
// Update registers with resolved info
__ load_field_entry(Rcache, index);
__ bind(L_done);
__ bind(resolved);
}
void TemplateTable::load_resolved_field_entry(Register obj,
@@ -3098,7 +3079,6 @@ void TemplateTable::fast_storefield(TosState state)
// R1: field offset, R2: field holder, R5: flags
load_resolved_field_entry(r2, r2, noreg, r1, r5);
__ verify_field_offset(r1);
{
Label notVolatile;
@@ -3188,8 +3168,6 @@ void TemplateTable::fast_accessfield(TosState state)
__ load_field_entry(r2, r1);
__ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
__ verify_field_offset(r1);
__ load_unsigned_byte(r3, Address(r2, in_bytes(ResolvedFieldEntry::flags_offset())));
// r0: object
@@ -3256,9 +3234,7 @@ void TemplateTable::fast_xaccess(TosState state)
__ ldr(r0, aaddress(0));
// access constant pool cache
__ load_field_entry(r2, r3, 2);
__ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
__ verify_field_offset(r1);
// 8179954: We need to make sure that the code generated for
// volatile accesses forms a sequentially-consistent set of
@@ -1,7 +1,6 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Red Hat Inc. All rights reserved.
* Copyright 2025 Arm Limited and/or its affiliates.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -223,13 +222,10 @@ void VM_Version::initialize() {
// Neoverse
// N1: 0xd0c
// N2: 0xd49
// N3: 0xd8e
// V1: 0xd40
// V2: 0xd4f
// V3: 0xd84
if (_cpu == CPU_ARM && (model_is(0xd0c) || model_is(0xd49) ||
model_is(0xd40) || model_is(0xd4f) ||
model_is(0xd8e) || model_is(0xd84))) {
model_is(0xd40) || model_is(0xd4f))) {
if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
}
@@ -264,9 +260,7 @@ void VM_Version::initialize() {
// Neoverse
// V1: 0xd40
// V2: 0xd4f
// V3: 0xd84
if (_cpu == CPU_ARM &&
(model_is(0xd40) || model_is(0xd4f) || model_is(0xd84))) {
if (_cpu == CPU_ARM && (model_is(0xd40) || model_is(0xd4f))) {
if (FLAG_IS_DEFAULT(UseCryptoPmullForCRC32)) {
FLAG_SET_DEFAULT(UseCryptoPmullForCRC32, true);
}
@@ -199,8 +199,6 @@ enum Ampere_CPU_Model {
constexpr static bool supports_secondary_supers_table() { return true; }
constexpr static bool supports_misaligned_vector_accesses() { return true; }
static void get_compatible_board(char *buf, int buflen);
static const SpinWait& spin_wait_desc() { return _spin_wait; }
+36
View File
@@ -1154,6 +1154,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return FP_REGP_mask();
}
bool maybe_far_call(const CallNode *n) {
return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
}
@@ -1244,6 +1248,23 @@ encode %{
__ set_inst_mark(mark);
%}
enc_class preserve_SP %{
// preserve mark
address mark = __ inst_mark();
DEBUG_ONLY(int off0 = __ offset());
// FP is preserved across all calls, even compiled calls.
// Use it to preserve SP in places where the callee might change the SP.
__ mov(Rmh_SP_save, SP);
DEBUG_ONLY(int off1 = __ offset());
assert(off1 - off0 == 4, "correct size prediction");
// restore mark
__ set_inst_mark(mark);
%}
enc_class restore_SP %{
__ mov(SP, Rmh_SP_save);
%}
enc_class Java_Dynamic_Call (method meth) %{
Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
assert(R8_ic_reg == Ricklass, "should be");
@@ -8778,6 +8799,7 @@ instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
// Call Java Static Instruction
instruct CallStaticJavaDirect( method meth ) %{
match(CallStaticJava);
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth);
ins_cost(CALL_COST);
@@ -8786,6 +8808,20 @@ instruct CallStaticJavaDirect( method meth ) %{
ins_pipe(simple_call);
%}
// Call Java Static Instruction (method handle version)
instruct CallStaticJavaHandle( method meth ) %{
match(CallStaticJava);
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
effect(USE meth);
// FP is saved by all callees (for interpreter stack correction).
// We use it here for a similar purpose, in {preserve,restore}_FP.
ins_cost(CALL_COST);
format %{ "CALL,static/MethodHandle ==> " %}
ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark );
ins_pipe(simple_call);
%}
// Call Java Dynamic Instruction
instruct CallDynamicJavaDirect( method meth ) %{
match(CallDynamicJava);
+3 -2
View File
@@ -1,5 +1,5 @@
//
// Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -432,7 +432,8 @@ OptoRegPair c2::return_value(int ideal_reg) {
int MachCallStaticJavaNode::ret_addr_offset() {
bool far = (_method == nullptr) ? maybe_far_call(this) : !cache_reachable();
return (far ? 3 : 1) * NativeInstruction::instruction_size;
return ((far ? 3 : 1) + (_method_handle_invoke ? 1 : 0)) *
NativeInstruction::instruction_size;
}
int MachCallDynamicJavaNode::ret_addr_offset() {
+5
View File
@@ -174,6 +174,11 @@ LIR_Opr FrameMap::stack_pointer() {
return FrameMap::SP_opr;
}
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
assert(Rmh_SP_save == FP, "Fix register used for saving SP for MethodHandle calls");
return FP_opr;
}
bool FrameMap::validate_frame() {
int max_offset = in_bytes(framesize_in_bytes());
int java_index = 0;
+12
View File
@@ -275,6 +275,14 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe
}
static void restore_sp_for_method_handle(StubAssembler* sasm) {
// Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site.
__ ldr_s32(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset()));
__ cmp(Rtemp, 0);
__ mov(SP, Rmh_SP_save, ne);
}
OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) {
__ block_comment("generate_handle_exception");
@@ -331,6 +339,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) {
break;
case StubId::c1_handle_exception_from_callee_id:
restore_live_registers_without_return(sasm); // must not jump immediately to handler
restore_sp_for_method_handle(sasm);
__ ret();
break;
default: ShouldNotReachHere();
@@ -363,6 +372,9 @@ void Runtime1::generate_unwind_exception(StubAssembler* sasm) {
// Jump to handler
__ verify_not_null_oop(Rexception_obj);
// JSR292 extension
restore_sp_for_method_handle(sasm);
__ jump(R0);
}
+50
View File
@@ -329,6 +329,56 @@ JavaThread** frame::saved_thread_address(const frame& f) {
return nullptr;
}
//------------------------------------------------------------------------------
// frame::verify_deopt_original_pc
//
// Verifies the calculated original PC of a deoptimization PC for the
// given unextended SP. The unextended SP might also be the saved SP
// for MethodHandle call sites.
#ifdef ASSERT
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) {
frame fr;
// This is ugly but it's better than to change {get,set}_original_pc
// to take an SP value as argument. And it's only a debugging
// method anyway.
fr._unextended_sp = unextended_sp;
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
}
#endif
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
void frame::adjust_unextended_sp() {
// same as on x86
// If we are returning to a compiled MethodHandle call site, the
// saved_fp will in fact be a saved value of the unextended SP. The
// simplest way to tell whether we are returning to such a call site
// is as follows:
nmethod* sender_nm = (_cb == nullptr) ? nullptr : _cb->as_nmethod_or_null();
if (sender_nm != nullptr) {
// If the sender PC is a deoptimization point, get the original
// PC. For MethodHandle call site the unextended_sp is stored in
// saved_fp.
if (sender_nm->is_deopt_mh_entry(_pc)) {
DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp));
_unextended_sp = _fp;
}
else if (sender_nm->is_deopt_entry(_pc)) {
DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));
}
else if (sender_nm->is_method_handle_return(_pc)) {
_unextended_sp = _fp;
}
}
}
//------------------------------------------------------------------------------
// frame::update_map_with_saved_link
void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
+10 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -85,11 +85,20 @@
// original sp.
intptr_t* _unextended_sp;
void adjust_unextended_sp();
intptr_t* ptr_at_addr(int offset) const {
return (intptr_t*) addr_at(offset);
}
#ifdef ASSERT
// Used in frame::sender_for_{interpreter,compiled}_frame
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false);
static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) {
verify_deopt_original_pc(nm, unextended_sp, true);
}
#endif
public:
// Constructors
+3 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,6 +112,8 @@ inline void frame::init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, add
}
inline void frame::setup(address pc) {
adjust_unextended_sp();
address original_pc = get_deopt_original_pc();
if (original_pc != nullptr) {
_pc = original_pc;
+2 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -364,6 +364,7 @@ class VFPSystemRegisterImpl : public AbstractRegisterImpl {
// This does not seem to conflict with Rexception_pc
// In case of issues, R3 might be OK but adapters calling the runtime would have to save it
#define R5_mh R5 // MethodHandle register, used during the call setup
#define Rmh_SP_save FP // for C1
/*
* C++ Interpreter Register Defines
+5
View File
@@ -264,6 +264,11 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
__ raw_pop(FP, LR);
// Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site.
__ ldr(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset()));
__ cmp(Rtemp, 0);
__ mov(SP, Rmh_SP_save, ne);
// R0 contains handler address
// Since this may be the deopt blob we must set R5 to look like we returned
// from the original pc that threw the exception
+1 -1
View File
@@ -2059,12 +2059,12 @@ class Assembler : public AbstractAssembler {
protected:
inline void tdi_unchecked(int tobits, Register a, int si16);
inline void twi_unchecked(int tobits, Register a, int si16);
public:
inline void tdi( int tobits, Register a, int si16); // asserts UseSIGTRAP
inline void twi( int tobits, Register a, int si16); // asserts UseSIGTRAP
inline void td( int tobits, Register a, Register b); // asserts UseSIGTRAP
inline void tw( int tobits, Register a, Register b); // asserts UseSIGTRAP
public:
static bool is_tdi(int x, int tobits, int ra, int si16) {
return (TDI_OPCODE == (x & TDI_OPCODE_MASK))
&& (tobits == inv_to_field(x))
-649
View File
@@ -1,649 +0,0 @@
/*
* Copyright (c) 1997, 2025, 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.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef CPU_PPC_ATOMICACCESS_PPC_HPP
#define CPU_PPC_ATOMICACCESS_PPC_HPP
#ifndef PPC64
#error "Atomic currently only implemented for PPC64"
#endif
#include "orderAccess_ppc.hpp"
#include "utilities/debug.hpp"
// Implementation of class AtomicAccess
//
// machine barrier instructions:
//
// - sync two-way memory barrier, aka fence
// - lwsync orders Store|Store,
// Load|Store,
// Load|Load,
// but not Store|Load
// - eieio orders memory accesses for device memory (only)
// - isync invalidates speculatively executed instructions
// From the POWER ISA 2.06 documentation:
// "[...] an isync instruction prevents the execution of
// instructions following the isync until instructions
// preceding the isync have completed, [...]"
// From IBM's AIX assembler reference:
// "The isync [...] instructions causes the processor to
// refetch any instructions that might have been fetched
// prior to the isync instruction. The instruction isync
// causes the processor to wait for all previous instructions
// to complete. Then any instructions already fetched are
// discarded and instruction processing continues in the
// environment established by the previous instructions."
//
// semantic barrier instructions:
// (as defined in orderAccess.hpp)
//
// - release orders Store|Store, (maps to lwsync)
// Load|Store
// - acquire orders Load|Store, (maps to lwsync)
// Load|Load
// - fence orders Store|Store, (maps to sync)
// Load|Store,
// Load|Load,
// Store|Load
//
inline void pre_membar(atomic_memory_order order) {
switch (order) {
case memory_order_relaxed:
case memory_order_acquire: break;
case memory_order_release:
case memory_order_acq_rel: __asm__ __volatile__ ("lwsync" : : : "memory"); break;
default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
}
}
inline void post_membar(atomic_memory_order order) {
switch (order) {
case memory_order_relaxed:
case memory_order_release: break;
case memory_order_acquire:
case memory_order_acq_rel: __asm__ __volatile__ ("isync" : : : "memory"); break;
default /*conservative*/ : __asm__ __volatile__ ("sync" : : : "memory"); break;
}
}
template<size_t byte_size>
struct AtomicAccess::PlatformAdd {
template<typename D, typename I>
D add_then_fetch(D volatile* dest, I add_value, atomic_memory_order order) const;
template<typename D, typename I>
D fetch_then_add(D volatile* dest, I add_value, atomic_memory_order order) const {
return add_then_fetch(dest, add_value, order) - add_value;
}
};
template<>
template<typename D, typename I>
inline D AtomicAccess::PlatformAdd<4>::add_then_fetch(D volatile* dest, I add_value,
atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(I));
STATIC_ASSERT(4 == sizeof(D));
D result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[result], 0, %[dest] \n"
" add %[result], %[result], %[add_value] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [add_value] "r" (add_value),
[dest] "b" (dest)
: "cc", "memory" );
post_membar(order);
return result;
}
template<>
template<typename D, typename I>
inline D AtomicAccess::PlatformAdd<8>::add_then_fetch(D volatile* dest, I add_value,
atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(I));
STATIC_ASSERT(8 == sizeof(D));
D result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[result], 0, %[dest] \n"
" add %[result], %[result], %[add_value] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [add_value] "r" (add_value),
[dest] "b" (dest)
: "cc", "memory" );
post_membar(order);
return result;
}
template<>
template<typename T>
inline T AtomicAccess::PlatformXchg<4>::operator()(T volatile* dest,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
// Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
pre_membar(order);
__asm__ __volatile__ (
/* atomic loop */
"1: \n"
" lwarx %[old_value], 0, %[dest] \n"
" stwcx. %[exchange_value], 0, %[dest] \n"
" bne- 1b \n"
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value)
/* in */
: [dest] "b" (dest),
[exchange_value] "r" (exchange_value)
/* clobber */
: "cc",
"memory"
);
post_membar(order);
return old_value;
}
template<>
template<typename T>
inline T AtomicAccess::PlatformXchg<8>::operator()(T volatile* dest,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
// Note that xchg doesn't necessarily do an acquire
// (see synchronizer.cpp).
T old_value;
pre_membar(order);
__asm__ __volatile__ (
/* atomic loop */
"1: \n"
" ldarx %[old_value], 0, %[dest] \n"
" stdcx. %[exchange_value], 0, %[dest] \n"
" bne- 1b \n"
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value)
/* in */
: [dest] "b" (dest),
[exchange_value] "r" (exchange_value)
/* clobber */
: "cc",
"memory"
);
post_membar(order);
return old_value;
}
template<>
template<typename T>
inline T AtomicAccess::PlatformCmpxchg<1>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(1 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
// specified otherwise (see atomicAccess.hpp).
const unsigned int masked_compare_val = (unsigned int)(unsigned char)compare_value;
unsigned int old_value;
pre_membar(order);
__asm__ __volatile__ (
/* simple guard */
" lbz %[old_value], 0(%[dest]) \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" lbarx %[old_value], 0, %[dest] \n"
" cmpw %[masked_compare_val], %[old_value] \n"
" bne- 2f \n"
" stbcx. %[exchange_value], 0, %[dest] \n"
" bne- 1b \n"
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value)
/* in */
: [dest] "b" (dest),
[masked_compare_val] "r" (masked_compare_val),
[exchange_value] "r" (exchange_value)
/* clobber */
: "cc",
"memory"
);
post_membar(order);
return PrimitiveConversions::cast<T>((unsigned char)old_value);
}
template<>
template<typename T>
inline T AtomicAccess::PlatformCmpxchg<4>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
// specified otherwise (see atomicAccess.hpp).
T old_value;
pre_membar(order);
__asm__ __volatile__ (
/* simple guard */
" lwz %[old_value], 0(%[dest]) \n"
" cmpw %[compare_value], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" lwarx %[old_value], 0, %[dest] \n"
" cmpw %[compare_value], %[old_value] \n"
" bne- 2f \n"
" stwcx. %[exchange_value], 0, %[dest] \n"
" bne- 1b \n"
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value)
/* in */
: [dest] "b" (dest),
[compare_value] "r" (compare_value),
[exchange_value] "r" (exchange_value)
/* clobber */
: "cc",
"memory"
);
post_membar(order);
return old_value;
}
template<>
template<typename T>
inline T AtomicAccess::PlatformCmpxchg<8>::operator()(T volatile* dest,
T compare_value,
T exchange_value,
atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
// Note that cmpxchg guarantees a two-way memory barrier across
// the cmpxchg, so it's really a 'fence_cmpxchg_fence' if not
// specified otherwise (see atomicAccess.hpp).
T old_value;
pre_membar(order);
__asm__ __volatile__ (
/* simple guard */
" ld %[old_value], 0(%[dest]) \n"
" cmpd %[compare_value], %[old_value] \n"
" bne- 2f \n"
/* atomic loop */
"1: \n"
" ldarx %[old_value], 0, %[dest] \n"
" cmpd %[compare_value], %[old_value] \n"
" bne- 2f \n"
" stdcx. %[exchange_value], 0, %[dest] \n"
" bne- 1b \n"
/* exit */
"2: \n"
/* out */
: [old_value] "=&r" (old_value)
/* in */
: [dest] "b" (dest),
[compare_value] "r" (compare_value),
[exchange_value] "r" (exchange_value)
/* clobber */
: "cc",
"memory"
);
post_membar(order);
return old_value;
}
template<size_t byte_size>
struct AtomicAccess::PlatformOrderedLoad<byte_size, X_ACQUIRE>
{
template <typename T>
T operator()(const volatile T* p) const {
T t = AtomicAccess::load(p);
// Use twi-isync for load_acquire (faster than lwsync).
__asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (t) : "memory");
return t;
}
};
template<>
class AtomicAccess::PlatformBitops<4, true> {
public:
template<typename T>
T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[old_value], 0, %[dest] \n"
" and %[result], %[old_value], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[old_value], 0, %[dest] \n"
" or %[result], %[old_value], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[old_value], 0, %[dest] \n"
" xor %[result], %[old_value], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[result], 0, %[dest] \n"
" and %[result], %[result], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
template<typename T>
T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[result], 0, %[dest] \n"
" or %[result], %[result], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
template<typename T>
T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(4 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: lwarx %[result], 0, %[dest] \n"
" xor %[result], %[result], %[bits] \n"
" stwcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
};
template<>
class AtomicAccess::PlatformBitops<8, true> {
public:
template<typename T>
T fetch_then_and(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[old_value], 0, %[dest] \n"
" and %[result], %[old_value], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T fetch_then_or(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[old_value], 0, %[dest] \n"
" or %[result], %[old_value], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T fetch_then_xor(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T old_value, result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[old_value], 0, %[dest] \n"
" xor %[result], %[old_value], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [old_value] "=&r" (old_value),
[result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return old_value;
}
template<typename T>
T and_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[result], 0, %[dest] \n"
" and %[result], %[result], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
template<typename T>
T or_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[result], 0, %[dest] \n"
" or %[result], %[result], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
template<typename T>
T xor_then_fetch(T volatile* dest, T bits, atomic_memory_order order) const {
STATIC_ASSERT(8 == sizeof(T));
T result;
pre_membar(order);
__asm__ __volatile__ (
"1: ldarx %[result], 0, %[dest] \n"
" xor %[result], %[result], %[bits] \n"
" stdcx. %[result], 0, %[dest] \n"
" bne- 1b \n"
: [result] "=&r" (result)
: [dest] "b" (dest),
[bits] "r" (bits)
: "cc", "memory" );
post_membar(order);
return result;
}
};
#endif // CPU_PPC_ATOMICACCESS_PPC_HPP
+9
View File
@@ -374,6 +374,15 @@ LIR_Opr FrameMap::stack_pointer() {
return SP_opr;
}
// JSR 292
// On PPC64, there is no need to save the SP, because neither
// method handle intrinsics, nor compiled lambda forms modify it.
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
return LIR_OprFact::illegalOpr;
}
bool FrameMap::validate_frame() {
int max_offset = in_bytes(framesize_in_bytes());
int java_index = 0;
@@ -193,19 +193,14 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register t
// Low order half of 64 bit value is currently used.
__ ld(R0, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), R16_thread);
__ cmpw(CR0, R0, tmp);
if (TrapBasedNMethodEntryBarriers) {
__ tw(Assembler::traptoLessThanUnsigned | Assembler::traptoGreaterThanUnsigned, R0, tmp);
} else {
__ cmpw(CR0, R0, tmp);
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
// Load stub address using toc (fixed instruction size, unlike load_const_optimized)
__ calculate_address_from_global_toc(tmp, StubRoutines::method_entry_barrier(),
true, true, false); // 2 instructions
__ mtctr(tmp);
__ bnectrl(CR0);
}
__ bnectrl(CR0);
// Oops may have been changed. Make those updates observable.
// "isync" can serve both, data and instruction patching.
@@ -100,21 +100,17 @@ public:
verify_op_code(current_instruction, Assembler::LD_OPCODE);
if (TrapBasedNMethodEntryBarriers) {
verify_op_code(current_instruction, Assembler::TW_OPCODE);
} else {
// cmpw (mnemonic)
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
// cmpw (mnemonic)
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
// calculate_address_from_global_toc (compound instruction)
verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction));
// bnectrl (mnemonic) (weak check; not checking the exact type)
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
}
// bnectrl (mnemonic) (weak check; not checking the exact type)
verify_op_code(current_instruction, Assembler::BCCTR_OPCODE);
// isync is optional
}
@@ -135,10 +131,9 @@ private:
static NativeNMethodBarrier* get_nmethod_barrier(nmethod* nm) {
BarrierSetAssembler* bs_asm = BarrierSet::barrier_set()->barrier_set_assembler();
address barrier_address = nm->code_begin() + nm->frame_complete_offset() -
(TrapBasedNMethodEntryBarriers ? 4 : 8) * BytesPerInstWord;
address barrier_address = nm->code_begin() + nm->frame_complete_offset() + (-8 * 4);
if (bs_asm->nmethod_patching_type() != NMethodPatchingType::stw_instruction_and_data_patch) {
barrier_address -= BytesPerInstWord; // isync (see nmethod_entry_barrier)
barrier_address -= 4; // isync (see nmethod_entry_barrier)
}
auto barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -43,6 +43,8 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
#define SUPPORTS_NATIVE_CX8
#define SUPPORT_MONITOR_COUNT
// PPC64 is not specified as multi-copy-atomic
// So we must not #define CPU_MULTI_COPY_ATOMIC
-2
View File
@@ -145,8 +145,6 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong);
"switch off all optimizations requiring SIGTRAP.") \
product(bool, TrapBasedICMissChecks, true, DIAGNOSTIC, \
"Raise and handle SIGTRAP if inline cache miss detected.") \
product(bool, TrapBasedNMethodEntryBarriers, true, DIAGNOSTIC, \
"Raise and handle SIGTRAP if nmethod entry barrier armed.") \
\
product(bool, TraceTraps, false, DIAGNOSTIC, \
"Trace all traps the signal handler handles.") \
+6 -4
View File
@@ -33,17 +33,17 @@ public:
// 2 - saving a current state (javaCalls)
// 3 - restoring an old state (javaCalls)
// No hardware barriers are necessary. All members are volatile and the profiler
// is run from a signal handler and only observers the thread its running on.
inline void clear(void) {
// clearing _last_Java_sp must be first
_last_Java_sp = nullptr;
// fence?
OrderAccess::release();
_last_Java_pc = nullptr;
}
inline void set(intptr_t* sp, address pc) {
_last_Java_pc = pc;
OrderAccess::release();
_last_Java_sp = sp;
}
@@ -56,9 +56,11 @@ public:
// unless the value is changing.
if (_last_Java_sp != src->_last_Java_sp) {
_last_Java_sp = nullptr;
OrderAccess::release();
}
_last_Java_pc = src->_last_Java_pc;
// Must be last so profiler will always see valid frame if has_last_frame() is true.
OrderAccess::release();
_last_Java_sp = src->_last_Java_sp;
}
@@ -73,6 +75,6 @@ public:
intptr_t* last_Java_fp() const { return *(intptr_t**)_last_Java_sp; }
void set_last_Java_sp(intptr_t* sp) { _last_Java_sp = sp; }
void set_last_Java_sp(intptr_t* sp) { OrderAccess::release(); _last_Java_sp = sp; }
#endif // CPU_PPC_JAVAFRAMEANCHOR_PPC_HPP
+1 -1
View File
@@ -402,7 +402,7 @@ void NativePostCallNop::make_deopt() {
bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) {
int32_t i2, i1;
assert(is_aligned(cb_offset, 4), "cb offset alignment does not match instruction alignment");
assert(!decode(i1, i2) || NMethodRelocation, "already patched");
assert(!decode(i1, i2), "already patched");
cb_offset = cb_offset >> 2;
if (((oopmap_slot & ppc_oopmap_slot_mask) != oopmap_slot) || ((cb_offset & ppc_cb_offset_mask) != cb_offset)) {
-6
View File
@@ -77,12 +77,6 @@ class NativeInstruction {
}
#endif
bool is_sigtrap_nmethod_entry_barrier() {
assert(UseSIGTRAP && TrapBasedNMethodEntryBarriers, "precondition");
return Assembler::is_tw(long_at(0), Assembler::traptoLessThanUnsigned | Assembler::traptoGreaterThanUnsigned,
0, -1);
}
bool is_safepoint_poll() {
// The current arguments of the instruction are not checked!
if (USE_POLL_BIT_ONLY) {
-86
View File
@@ -1,86 +0,0 @@
/*
* Copyright (c) 1997, 2025, 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.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef CPU_PPC_ORDERACCESS_PPC_HPP
#define CPU_PPC_ORDERACCESS_PPC_HPP
#ifndef PPC64
#error "OrderAccess currently only implemented for PPC64"
#endif
// Compiler version last used for testing: gcc 4.1.2
// Please update this information when this file changes
// Implementation of class OrderAccess.
//
// Machine barrier instructions:
//
// - sync Two-way memory barrier, aka fence.
// - lwsync orders Store|Store,
// Load|Store,
// Load|Load,
// but not Store|Load
// - eieio orders Store|Store
// - isync Invalidates speculatively executed instructions,
// but isync may complete before storage accesses
// associated with instructions preceding isync have
// been performed.
//
// Semantic barrier instructions:
// (as defined in orderAccess.hpp)
//
// - release orders Store|Store, (maps to lwsync)
// Load|Store
// - acquire orders Load|Store, (maps to lwsync)
// Load|Load
// - fence orders Store|Store, (maps to sync)
// Load|Store,
// Load|Load,
// Store|Load
//
#define inlasm_sync() __asm__ __volatile__ ("sync" : : : "memory");
#define inlasm_lwsync() __asm__ __volatile__ ("lwsync" : : : "memory");
#define inlasm_eieio() __asm__ __volatile__ ("eieio" : : : "memory");
#define inlasm_isync() __asm__ __volatile__ ("isync" : : : "memory");
inline void OrderAccess::loadload() { inlasm_lwsync(); }
inline void OrderAccess::storestore() { inlasm_lwsync(); }
inline void OrderAccess::loadstore() { inlasm_lwsync(); }
inline void OrderAccess::storeload() { inlasm_sync(); }
inline void OrderAccess::acquire() { inlasm_lwsync(); }
inline void OrderAccess::release() { inlasm_lwsync(); }
inline void OrderAccess::fence() { inlasm_sync(); }
inline void OrderAccess::cross_modify_fence_impl()
{ inlasm_isync(); }
#undef inlasm_sync
#undef inlasm_lwsync
#undef inlasm_eieio
#undef inlasm_isync
#endif // CPU_PPC_ORDERACCESS_PPC_HPP
+5
View File
@@ -2473,6 +2473,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return RegMask();
}
%}
//----------ENCODING BLOCK-----------------------------------------------------
@@ -3430,6 +3434,7 @@ encode %{
// Create the call node.
CallDynamicJavaDirectSchedNode *call = new CallDynamicJavaDirectSchedNode();
call->_method_handle_invoke = _method_handle_invoke;
call->_vtable_index = _vtable_index;
call->_method = _method;
call->_optimized_virtual = _optimized_virtual;
+56 -2
View File
@@ -1639,6 +1639,7 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj,
assert_different_registers(reg_cont_obj, reg_flags);
Register zero = R8_ARG6;
Register tmp2 = R9_ARG7;
Register tmp3 = R10_ARG8;
DEBUG_ONLY(__ block_comment("fill {"));
#ifdef ASSERT
@@ -1654,9 +1655,12 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj,
__ stw(zero, in_bytes(ContinuationEntry::pin_count_offset()), R1_SP);
__ ld_ptr(tmp2, JavaThread::cont_fastpath_offset(), R16_thread);
__ ld(tmp3, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
__ st_ptr(tmp2, ContinuationEntry::parent_cont_fastpath_offset(), R1_SP);
__ std(tmp3, in_bytes(ContinuationEntry::parent_held_monitor_count_offset()), R1_SP);
__ st_ptr(zero, JavaThread::cont_fastpath_offset(), R16_thread);
__ std(zero, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
DEBUG_ONLY(__ block_comment("} fill"));
}
@@ -1677,6 +1681,7 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj,
static void continuation_enter_cleanup(MacroAssembler* masm) {
Register tmp1 = R8_ARG6;
Register tmp2 = R9_ARG7;
Register tmp3 = R10_ARG8;
#ifdef ASSERT
__ block_comment("clean {");
@@ -1687,8 +1692,57 @@ static void continuation_enter_cleanup(MacroAssembler* masm) {
__ ld_ptr(tmp1, ContinuationEntry::parent_cont_fastpath_offset(), R1_SP);
__ st_ptr(tmp1, JavaThread::cont_fastpath_offset(), R16_thread);
__ ld_ptr(tmp2, ContinuationEntry::parent_offset(), R1_SP);
__ st_ptr(tmp2, JavaThread::cont_entry_offset(), R16_thread);
if (CheckJNICalls) {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ lwz(R0, in_bytes(ContinuationEntry::flags_offset()), R1_SP);
__ cmpwi(CR0, R0, 0);
__ beq(CR0, L_skip_vthread_code);
// If the held monitor count is > 0 and this vthread is terminating then
// it failed to release a JNI monitor. So we issue the same log message
// that JavaThread::exit does.
__ ld(R0, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread);
__ cmpdi(CR0, R0, 0);
__ beq(CR0, L_skip_vthread_code);
// Save return value potentially containing the exception oop
Register ex_oop = R15_esp; // nonvolatile register
__ mr(ex_oop, R3_RET);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held));
// Restore potental return value
__ mr(R3_RET, ex_oop);
// For vthreads we have to explicitly zero the JNI monitor count of the carrier
// on termination. The held count is implicitly zeroed below when we restore from
// the parent held count (which has to be zero).
__ li(tmp1, 0);
__ std(tmp1, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread);
__ bind(L_skip_vthread_code);
}
#ifdef ASSERT
else {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ lwz(R0, in_bytes(ContinuationEntry::flags_offset()), R1_SP);
__ cmpwi(CR0, R0, 0);
__ beq(CR0, L_skip_vthread_code);
// See comment just above. If not checking JNI calls the JNI count is only
// needed for assertion checking.
__ li(tmp1, 0);
__ std(tmp1, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread);
__ bind(L_skip_vthread_code);
}
#endif
__ ld(tmp2, in_bytes(ContinuationEntry::parent_held_monitor_count_offset()), R1_SP);
__ ld_ptr(tmp3, ContinuationEntry::parent_offset(), R1_SP);
__ std(tmp2, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread);
__ st_ptr(tmp3, JavaThread::cont_entry_offset(), R16_thread);
DEBUG_ONLY(__ block_comment("} clean"));
}
+33 -38
View File
@@ -2179,11 +2179,17 @@ void TemplateTable::_return(TosState state) {
// - Rscratch
void TemplateTable::resolve_cache_and_index_for_method(int byte_no, Register Rcache, Register Rscratch) {
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
Label L_clinit_barrier_slow, L_done;
Label Lresolved, Ldone, L_clinit_barrier_slow;
Register Rindex = Rscratch;
Bytecodes::Code code = bytecode();
switch (code) {
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
default:
break;
}
const int bytecode_offset = (byte_no == f1_byte) ? in_bytes(ResolvedMethodEntry::bytecode1_offset())
: in_bytes(ResolvedMethodEntry::bytecode2_offset());
__ load_method_entry(Rcache, Rindex);
@@ -2191,8 +2197,20 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no, Register Rca
__ lbz(Rscratch, bytecode_offset, Rcache);
// Acquire by cmp-br-isync (see below).
__ cmpdi(CR0, Rscratch, (int)code);
__ bne(CR0, L_clinit_barrier_slow);
__ beq(CR0, Lresolved);
// Class initialization barrier slow path lands here as well.
__ bind(L_clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ li(R4_ARG2, code);
__ call_VM(noreg, entry, R4_ARG2, true);
// Update registers with resolved info.
__ load_method_entry(Rcache, Rindex);
__ b(Ldone);
__ bind(Lresolved);
__ isync(); // Order load wrt. succeeding loads.
// Class initialization barrier for static methods
@@ -2202,26 +2220,18 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no, Register Rca
__ ld(method, in_bytes(ResolvedMethodEntry::method_offset()), Rcache);
__ load_method_holder(klass, method);
__ clinit_barrier(klass, R16_thread, &L_done, /*L_slow_path*/ nullptr);
} else {
__ b(L_done);
__ clinit_barrier(klass, R16_thread, nullptr /*L_fast_path*/, &L_clinit_barrier_slow);
}
// Class initialization barrier slow path lands here as well.
__ bind(L_clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ li(R4_ARG2, code);
__ call_VM(noreg, entry, R4_ARG2);
// Update registers with resolved info.
__ load_method_entry(Rcache, Rindex);
__ bind(L_done);
__ bind(Ldone);
}
void TemplateTable::resolve_cache_and_index_for_field(int byte_no, Register Rcache, Register index) {
void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
Register Rcache,
Register index) {
assert_different_registers(Rcache, index);
Label L_clinit_barrier_slow, L_done;
Label resolved;
Bytecodes::Code code = bytecode();
switch (code) {
@@ -2236,34 +2246,19 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no, Register Rcac
: in_bytes(ResolvedFieldEntry::put_code_offset());
__ lbz(R0, code_offset, Rcache);
__ cmpwi(CR0, R0, (int)code); // have we resolved this bytecode?
__ bne(CR0, L_clinit_barrier_slow);
__ isync(); // Order load wrt. succeeding loads.
// Class initialization barrier for static fields
if (VM_Version::supports_fast_class_init_checks() &&
(bytecode() == Bytecodes::_getstatic || bytecode() == Bytecodes::_putstatic)) {
const Register field_holder = R4_ARG2;
// InterpreterRuntime::resolve_get_put sets field_holder and finally release-stores put_code.
// We have seen the released put_code above and will read the corresponding field_holder and init_state
// (ordered by compare-branch-isync).
__ ld(field_holder, ResolvedFieldEntry::field_holder_offset(), Rcache);
__ clinit_barrier(field_holder, R16_thread, &L_done, /*L_slow_path*/ nullptr);
} else {
__ b(L_done);
}
__ beq(CR0, resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
__ bind(L_clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ li(R4_ARG2, code);
__ li(R4_ARG2, (int)code);
__ call_VM(noreg, entry, R4_ARG2);
// Update registers with resolved info
__ load_field_entry(Rcache, index);
__ bind(L_done);
__ bind(resolved);
// Use acquire semantics for the bytecode (see ResolvedFieldEntry::fill_in()).
__ isync(); // Order load wrt. succeeding loads.
}
void TemplateTable::load_resolved_field_entry(Register obj,
+2 -8
View File
@@ -87,10 +87,8 @@ void VM_Version::initialize() {
if (!UseSIGTRAP) {
MSG(TrapBasedICMissChecks);
MSG(TrapBasedNullChecks);
MSG(TrapBasedNMethodEntryBarriers);
FLAG_SET_ERGO(TrapBasedNullChecks, false);
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
FLAG_SET_ERGO(TrapBasedNMethodEntryBarriers, false);
FLAG_SET_ERGO(TrapBasedNullChecks, false);
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
}
#ifdef COMPILER2
@@ -99,10 +97,6 @@ void VM_Version::initialize() {
FLAG_SET_ERGO(TrapBasedRangeChecks, false);
}
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
FLAG_SET_ERGO(UsePopCountInstruction, true);
}
if (PowerArchitecturePPC64 >= 9) {
// Performance is good since Power9.
if (FLAG_IS_DEFAULT(SuperwordUseVSX)) {
-1
View File
@@ -64,7 +64,6 @@ public:
constexpr static bool supports_stack_watermark_barrier() { return true; }
constexpr static bool supports_recursive_lightweight_locking() { return true; }
constexpr static bool supports_secondary_supers_table() { return true; }
constexpr static bool supports_misaligned_vector_accesses() { return true; }
static bool supports_float16() { return PowerArchitecturePPC64 >= 9; }
+11 -18
View File
@@ -914,17 +914,6 @@ protected:
public:
static uint32_t encode_csrrw(Register Rd, const uint32_t csr, Register Rs1) {
guarantee(is_uimm12(csr), "csr is invalid");
uint32_t insn = 0;
patch((address)&insn, 6, 0, 0b1110011);
patch((address)&insn, 14, 12, 0b001);
patch_reg((address)&insn, 7, Rd);
patch_reg((address)&insn, 15, Rs1);
patch((address)&insn, 31, 20, csr);
return insn;
}
static uint32_t encode_jal(Register Rd, const int32_t offset) {
guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid.");
uint32_t insn = 0;
@@ -3704,15 +3693,19 @@ public:
// --------------------------
// Upper Immediate Instruction
// --------------------------
void lui(Register Rd, int32_t imm) {
/* lui -> c.lui */
if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) {
c_lui(Rd, imm);
return;
}
_lui(Rd, imm);
#define INSN(NAME) \
void NAME(Register Rd, int32_t imm) { \
/* lui -> c.lui */ \
if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) { \
c_lui(Rd, imm); \
return; \
} \
_lui(Rd, imm); \
}
INSN(lui);
#undef INSN
// Cache Management Operations
// These instruction may be turned off for user space.
@@ -377,6 +377,11 @@ LIR_Opr FrameMap::stack_pointer() {
return FrameMap::sp_opr;
}
// JSR 292
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
return LIR_OprFact::illegalOpr; // Not needed on riscv
}
bool FrameMap::validate_frame() {
return true;
}
@@ -1350,7 +1350,6 @@ void LIR_Assembler::align_call(LIR_Code code) {
}
void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
Assembler::IncompressibleScope scope(_masm);
address call = __ reloc_call(Address(op->addr(), rtype));
if (call == nullptr) {
bailout("reloc call address stub overflow");
@@ -1361,7 +1360,6 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
}
void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
Assembler::IncompressibleScope scope(_masm);
address call = __ ic_call(op->addr());
if (call == nullptr) {
bailout("reloc call address stub overflow");
@@ -1844,10 +1842,6 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C
void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) {
assert(!tmp->is_valid(), "don't need temporary");
Assembler::IncompressibleScope scope(_masm);
// Post call nops must be natural aligned due to cmodx rules.
align_call(lir_rtcall);
__ rt_call(dest);
if (info != nullptr) {
+16 -131
View File
@@ -1687,7 +1687,6 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res
Register tmp4, Register tmp5, Register tmp6,
BasicType eltype)
{
assert(!UseRVV, "sanity");
assert_different_registers(ary, cnt, result, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, t0, t1);
const int elsize = arrays_hashcode_elsize(eltype);
@@ -1760,143 +1759,29 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res
BLOCK_COMMENT("} // arrays_hashcode");
}
void C2_MacroAssembler::arrays_hashcode_v(Register ary, Register cnt, Register result,
Register tmp1, Register tmp2, Register tmp3,
BasicType eltype)
{
assert(UseRVV, "sanity");
assert(StubRoutines::riscv::arrays_hashcode_powers_of_31() != nullptr, "sanity");
assert_different_registers(ary, cnt, result, tmp1, tmp2, tmp3, t0, t1);
// The MaxVectorSize should have been set by detecting RVV max vector register
// size when check UseRVV (i.e. MaxVectorSize == VM_Version::_initial_vector_length).
// Let's use T_INT as all hashCode calculations eventually deal with ints.
const int lmul = 2;
const int stride = MaxVectorSize / sizeof(jint) * lmul;
const int elsize_bytes = arrays_hashcode_elsize(eltype);
const int elsize_shift = exact_log2(elsize_bytes);
switch (eltype) {
case T_BOOLEAN: BLOCK_COMMENT("arrays_hashcode_v(unsigned byte) {"); break;
case T_CHAR: BLOCK_COMMENT("arrays_hashcode_v(char) {"); break;
case T_BYTE: BLOCK_COMMENT("arrays_hashcode_v(byte) {"); break;
case T_SHORT: BLOCK_COMMENT("arrays_hashcode_v(short) {"); break;
case T_INT: BLOCK_COMMENT("arrays_hashcode_v(int) {"); break;
default:
ShouldNotReachHere();
}
const Register pow31_highest = tmp1;
const Register ary_end = tmp2;
const Register consumed = tmp3;
const VectorRegister v_sum = v2;
const VectorRegister v_src = v4;
const VectorRegister v_coeffs = v6;
const VectorRegister v_tmp = v8;
const address adr_pows31 = StubRoutines::riscv::arrays_hashcode_powers_of_31()
+ sizeof(jint);
Label VEC_LOOP, DONE, SCALAR_TAIL, SCALAR_TAIL_LOOP;
// NB: at this point (a) 'result' already has some value,
// (b) 'cnt' is not 0 or 1, see java code for details.
andi(t0, cnt, ~(stride - 1));
beqz(t0, SCALAR_TAIL);
la(t1, ExternalAddress(adr_pows31));
lw(pow31_highest, Address(t1, -1 * sizeof(jint)));
vsetvli(consumed, cnt, Assembler::e32, Assembler::m2);
vle32_v(v_coeffs, t1); // 31^^(stride - 1) ... 31^^0
vmv_v_x(v_sum, x0);
bind(VEC_LOOP);
arrays_hashcode_elload_v(v_src, v_tmp, ary, eltype);
vmul_vv(v_src, v_src, v_coeffs);
vmadd_vx(v_sum, pow31_highest, v_src);
mulw(result, result, pow31_highest);
shadd(ary, consumed, ary, t0, elsize_shift);
subw(cnt, cnt, consumed);
andi(t1, cnt, ~(stride - 1));
bnez(t1, VEC_LOOP);
vmv_s_x(v_tmp, x0);
vredsum_vs(v_sum, v_sum, v_tmp);
vmv_x_s(t0, v_sum);
addw(result, result, t0);
beqz(cnt, DONE);
bind(SCALAR_TAIL);
shadd(ary_end, cnt, ary, t0, elsize_shift);
bind(SCALAR_TAIL_LOOP);
arrays_hashcode_elload(t0, Address(ary), eltype);
slli(t1, result, 5); // optimize 31 * result
subw(result, t1, result); // with result<<5 - result
addw(result, result, t0);
addi(ary, ary, elsize_bytes);
bne(ary, ary_end, SCALAR_TAIL_LOOP);
bind(DONE);
BLOCK_COMMENT("} // arrays_hashcode_v");
}
int C2_MacroAssembler::arrays_hashcode_elsize(BasicType eltype) {
switch (eltype) {
case T_BOOLEAN: return sizeof(jboolean);
case T_BYTE: return sizeof(jbyte);
case T_SHORT: return sizeof(jshort);
case T_CHAR: return sizeof(jchar);
case T_INT: return sizeof(jint);
default:
ShouldNotReachHere();
return -1;
case T_BOOLEAN: return sizeof(jboolean);
case T_BYTE: return sizeof(jbyte);
case T_SHORT: return sizeof(jshort);
case T_CHAR: return sizeof(jchar);
case T_INT: return sizeof(jint);
default:
ShouldNotReachHere();
return -1;
}
}
void C2_MacroAssembler::arrays_hashcode_elload(Register dst, Address src, BasicType eltype) {
switch (eltype) {
// T_BOOLEAN used as surrogate for unsigned byte
case T_BOOLEAN: lbu(dst, src); break;
case T_BYTE: lb(dst, src); break;
case T_SHORT: lh(dst, src); break;
case T_CHAR: lhu(dst, src); break;
case T_INT: lw(dst, src); break;
default:
ShouldNotReachHere();
}
}
void C2_MacroAssembler::arrays_hashcode_elload_v(VectorRegister vdst,
VectorRegister vtmp,
Register src,
BasicType eltype) {
assert_different_registers(vdst, vtmp);
switch (eltype) {
case T_BOOLEAN:
vle8_v(vtmp, src);
vzext_vf4(vdst, vtmp);
break;
case T_BYTE:
vle8_v(vtmp, src);
vsext_vf4(vdst, vtmp);
break;
case T_CHAR:
vle16_v(vtmp, src);
vzext_vf2(vdst, vtmp);
break;
case T_SHORT:
vle16_v(vtmp, src);
vsext_vf2(vdst, vtmp);
break;
case T_INT:
vle32_v(vdst, src);
break;
default:
ShouldNotReachHere();
// T_BOOLEAN used as surrogate for unsigned byte
case T_BOOLEAN: lbu(dst, src); break;
case T_BYTE: lb(dst, src); break;
case T_SHORT: lh(dst, src); break;
case T_CHAR: lhu(dst, src); break;
case T_INT: lw(dst, src); break;
default:
ShouldNotReachHere();
}
}
@@ -92,15 +92,11 @@
Register tmp3, Register tmp4,
Register tmp5, Register tmp6,
BasicType eltype);
// helper function for arrays_hashcode
int arrays_hashcode_elsize(BasicType eltype);
void arrays_hashcode_elload(Register dst, Address src, BasicType eltype);
void arrays_hashcode_v(Register ary, Register cnt, Register result,
Register tmp1, Register tmp2, Register tmp3,
BasicType eltype);
void arrays_hashcode_elload_v(VectorRegister vdst, VectorRegister vtmp,
Register src, BasicType eltype);
void string_equals(Register r1, Register r2,
Register result, Register cnt1);
+45 -1
View File
@@ -217,7 +217,8 @@ bool frame::safe_for_sender(JavaThread *thread) {
nmethod* nm = sender_blob->as_nmethod_or_null();
if (nm != nullptr) {
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
nm->method()->is_method_handle_intrinsic()) {
return false;
}
}
@@ -426,6 +427,49 @@ JavaThread** frame::saved_thread_address(const frame& f) {
return thread_addr;
}
//------------------------------------------------------------------------------
// frame::verify_deopt_original_pc
//
// Verifies the calculated original PC of a deoptimization PC for the
// given unextended SP.
#ifdef ASSERT
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
frame fr;
// This is ugly but it's better than to change {get,set}_original_pc
// to take an SP value as argument. And it's only a debugging
// method anyway.
fr._unextended_sp = unextended_sp;
assert_cond(nm != nullptr);
address original_pc = nm->get_original_pc(&fr);
assert(nm->insts_contains_inclusive(original_pc),
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
}
#endif
//------------------------------------------------------------------------------
// frame::adjust_unextended_sp
#ifdef ASSERT
void frame::adjust_unextended_sp() {
// On riscv, sites calling method handle intrinsics and lambda forms are treated
// as any other call site. Therefore, no special action is needed when we are
// returning to any of these call sites.
if (_cb != nullptr) {
nmethod* sender_nm = _cb->as_nmethod_or_null();
if (sender_nm != nullptr) {
// If the sender PC is a deoptimization point, get the original PC.
if (sender_nm->is_deopt_entry(_pc) ||
sender_nm->is_deopt_mh_entry(_pc)) {
verify_deopt_original_pc(sender_nm, _unextended_sp);
}
}
}
}
#endif
//------------------------------------------------------------------------------
// frame::sender_for_interpreter_frame
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
+8 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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.
*
@@ -179,10 +179,17 @@
int _offset_unextended_sp; // for use in stack-chunk frames
};
void adjust_unextended_sp() NOT_DEBUG_RETURN;
intptr_t* ptr_at_addr(int offset) const {
return (intptr_t*) addr_at(offset);
}
#ifdef ASSERT
// Used in frame::sender_for_{interpreter,compiled}_frame
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp);
#endif
public:
// Constructors
+4 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -114,6 +114,8 @@ inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
}
inline void frame::setup(address pc) {
adjust_unextended_sp();
address original_pc = get_deopt_original_pc();
if (original_pc != nullptr) {
_pc = original_pc;
@@ -213,6 +215,7 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) {
// value.
_cb = CodeCache::find_blob(_pc);
adjust_unextended_sp();
address original_pc = get_deopt_original_pc();
if (original_pc != nullptr) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2015, Red Hat Inc. 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.
@@ -44,6 +44,8 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
#define SUPPORTS_NATIVE_CX8
#define SUPPORT_MONITOR_COUNT
#define SUPPORT_RESERVED_STACK_AREA
#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY
@@ -1841,15 +1841,6 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index
}
#ifdef ASSERT
void InterpreterMacroAssembler::verify_field_offset(Register reg) {
// Verify the field offset is not in the header, implicitly checks for 0
Label L;
mv(t0, oopDesc::base_offset_in_bytes());
bge(reg, t0, L);
stop("bad field offset");
bind(L);
}
void InterpreterMacroAssembler::verify_access_flags(Register access_flags, uint32_t flag,
const char* msg, bool stop_by_hit) {
Label L;
@@ -300,8 +300,6 @@ class InterpreterMacroAssembler: public MacroAssembler {
void load_field_entry(Register cache, Register index, int bcp_offset = 1);
void load_method_entry(Register cache, Register index, int bcp_offset = 1);
void verify_field_offset(Register reg) NOT_DEBUG_RETURN;
#ifdef ASSERT
void verify_access_flags(Register access_flags, uint32_t flag,
const char* msg, bool stop_by_hit = true);
@@ -39,23 +39,25 @@ public:
// 3 - restoring an old state (javaCalls)
void clear(void) {
// No hardware barriers are necessary. All members are volatile and the profiler
// is run from a signal handler and the only observer is the thread its running on.
// clearing _last_Java_sp must be first
_last_Java_sp = nullptr;
OrderAccess::release();
_last_Java_fp = nullptr;
_last_Java_pc = nullptr;
}
void copy(JavaFrameAnchor* src) {
// No hardware barriers are necessary. All members are volatile and the profiler
// is run from a signal handler and the only observer is the thread its running on.
// In order to make sure the transition state is valid for "this"
// We must clear _last_Java_sp before copying the rest of the new data
//
// Hack Alert: Temporary bugfix for 4717480/4721647
// To act like previous version (pd_cache_state) don't null _last_Java_sp
// unless the value is changing
//
assert(src != nullptr, "Src should not be null.");
if (_last_Java_sp != src->_last_Java_sp) {
_last_Java_sp = nullptr;
OrderAccess::release();
}
_last_Java_fp = src->_last_Java_fp;
_last_Java_pc = src->_last_Java_pc;
+38 -11
View File
@@ -225,6 +225,36 @@ void MacroAssembler::pop_cont_fastpath(Register java_thread) {
bind(done);
}
void MacroAssembler::inc_held_monitor_count(Register tmp) {
Address dst(xthread, JavaThread::held_monitor_count_offset());
ld(tmp, dst);
addi(tmp, tmp, 1);
sd(tmp, dst);
#ifdef ASSERT
Label ok;
test_bit(tmp, tmp, 63);
beqz(tmp, ok);
STOP("assert(held monitor count overflow)");
should_not_reach_here();
bind(ok);
#endif
}
void MacroAssembler::dec_held_monitor_count(Register tmp) {
Address dst(xthread, JavaThread::held_monitor_count_offset());
ld(tmp, dst);
subi(tmp, tmp, 1);
sd(tmp, dst);
#ifdef ASSERT
Label ok;
test_bit(tmp, tmp, 63);
beqz(tmp, ok);
STOP("assert(held monitor count underflow)");
should_not_reach_here();
bind(ok);
#endif
}
int MacroAssembler::align(int modulus, int extra_offset) {
CompressibleScope scope(this);
intptr_t before = offset();
@@ -325,15 +355,14 @@ void MacroAssembler::call_VM(Register oop_result,
}
void MacroAssembler::post_call_nop() {
assert(!in_compressible_scope(), "Must be");
assert_alignment(pc());
if (!Continuations::enabled()) {
return;
}
relocate(post_call_nop_Relocation::spec());
InlineSkippedInstructionsCounter skipCounter(this);
nop();
li32(zr, 0);
relocate(post_call_nop_Relocation::spec(), [&] {
InlineSkippedInstructionsCounter skipCounter(this);
nop();
li32(zr, 0);
});
}
// these are no-ops overridden by InterpreterMacroAssembler
@@ -360,14 +389,12 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp,
last_java_sp = esp;
}
sd(last_java_sp, Address(xthread, JavaThread::last_Java_sp_offset()));
// last_java_fp is optional
if (last_java_fp->is_valid()) {
sd(last_java_fp, Address(xthread, JavaThread::last_Java_fp_offset()));
}
// We must set sp last.
sd(last_java_sp, Address(xthread, JavaThread::last_Java_sp_offset()));
}
void MacroAssembler::set_last_Java_frame(Register last_java_sp,
@@ -4986,7 +5013,7 @@ address MacroAssembler::reloc_call(Address entry, Register tmp) {
address MacroAssembler::ic_call(address entry, jint method_index) {
RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index);
assert(!in_compressible_scope(), "Must be");
IncompressibleScope scope(this); // relocations
movptr(t0, (address)Universe::non_oop_word(), t1);
assert_cond(entry != nullptr);
return reloc_call(Address(entry, rh));
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -849,6 +849,9 @@ public:
void push_cont_fastpath(Register java_thread = xthread);
void pop_cont_fastpath(Register java_thread = xthread);
void inc_held_monitor_count(Register tmp);
void dec_held_monitor_count(Register tmp);
// if heap base register is used - reinit it with the correct value
void reinit_heapbase();
+11 -14
View File
@@ -331,10 +331,13 @@ bool NativeInstruction::is_safepoint_poll() {
return MacroAssembler::is_lwu_to_zr(address(this));
}
void NativeIllegalInstruction::insert(address code_pos) {
assert_cond(code_pos != nullptr);
Assembler::sd_instr(code_pos, 0xffffffff); // all bits ones is permanently reserved as an illegal instruction
}
bool NativeInstruction::is_stop() {
// an illegal instruction, 'csrrw x0, time, x0'
uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::time, x0);
return uint_at(0) == encoded;
return uint_at(0) == 0xc0101073; // an illegal instruction, 'csrrw x0, time, x0'
}
//-------------------------------------------------------------------
@@ -344,8 +347,6 @@ void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
MacroAssembler a(&cb);
Assembler::IncompressibleScope scope(&a); // Fixed length: see NativeGeneralJump::get_instruction_size()
MacroAssembler::assert_alignment(code_pos);
int32_t offset = 0;
a.movptr(t1, entry, offset, t0); // lui, lui, slli, add
a.jr(t1, offset); // jalr
@@ -377,7 +378,6 @@ bool NativePostCallNop::decode(int32_t& oopmap_slot, int32_t& cb_offset) const {
}
bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) {
MacroAssembler::assert_alignment(addr_at(4));
if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) {
return false; // cannot encode
}
@@ -389,17 +389,14 @@ bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) {
return true; // successfully encoded
}
bool NativeDeoptInstruction::is_deopt_at(address instr) {
assert(instr != nullptr, "Must be");
uint32_t value = Assembler::ld_instr(instr);
uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0);
return value == encoded;
void NativeDeoptInstruction::verify() {
}
// Inserts an undefined instruction at a given pc
void NativeDeoptInstruction::insert(address code_pos) {
MacroAssembler::assert_alignment(code_pos);
uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0);
Assembler::sd_instr(code_pos, encoded);
// 0xc0201073 encodes CSRRW x0, instret, x0
uint32_t insn = 0xc0201073;
uint32_t *pos = (uint32_t *) code_pos;
*pos = insn;
ICache::invalidate_range(code_pos, 4);
}
+14 -1
View File
@@ -294,6 +294,12 @@ inline NativeGeneralJump* nativeGeneralJump_at(address addr) {
return jump;
}
class NativeIllegalInstruction: public NativeInstruction {
public:
// Insert illegal opcode as specific address
static void insert(address code_pos);
};
inline bool NativeInstruction::is_nop() const {
uint32_t insn = Assembler::ld_instr(addr_at(0));
return insn == 0x13;
@@ -347,7 +353,14 @@ class NativeDeoptInstruction: public NativeInstruction {
address instruction_address() const { return addr_at(instruction_offset); }
address next_instruction_address() const { return addr_at(instruction_size); }
static bool is_deopt_at(address instr);
void verify();
static bool is_deopt_at(address instr) {
assert(instr != nullptr, "");
uint32_t value = Assembler::ld_instr(instr);
// 0xc0201073 encodes CSRRW x0, instret, x0
return value == 0xc0201073;
}
// MT-safe patching
static void insert(address code_pos);
+22 -43
View File
@@ -1093,39 +1093,39 @@ RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask;
void reg_mask_init() {
_ANY_REG32_mask = _ALL_REG32_mask;
_ANY_REG32_mask.remove(OptoReg::as_OptoReg(x0->as_VMReg()));
_ANY_REG32_mask.Remove(OptoReg::as_OptoReg(x0->as_VMReg()));
_ANY_REG_mask = _ALL_REG_mask;
_ANY_REG_mask.subtract(_ZR_REG_mask);
_ANY_REG_mask.SUBTRACT(_ZR_REG_mask);
_PTR_REG_mask = _ALL_REG_mask;
_PTR_REG_mask.subtract(_ZR_REG_mask);
_PTR_REG_mask.SUBTRACT(_ZR_REG_mask);
_NO_SPECIAL_REG32_mask = _ALL_REG32_mask;
_NO_SPECIAL_REG32_mask.subtract(_NON_ALLOCATABLE_REG32_mask);
_NO_SPECIAL_REG32_mask.SUBTRACT(_NON_ALLOCATABLE_REG32_mask);
_NO_SPECIAL_REG_mask = _ALL_REG_mask;
_NO_SPECIAL_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_PTR_REG_mask = _ALL_REG_mask;
_NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
_NO_SPECIAL_PTR_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask);
// x27 is not allocatable when compressed oops is on
if (UseCompressedOops) {
_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()));
_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()));
}
// x8 is not allocatable when PreserveFramePointer is on
if (PreserveFramePointer) {
_NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
}
_NO_SPECIAL_NO_FP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask;
_NO_SPECIAL_NO_FP_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg()));
_NO_SPECIAL_NO_FP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg()));
}
void PhaseOutput::pd_perform_mach_node_analysis() {
@@ -1269,26 +1269,6 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const
return align_up(current_offset, alignment_required()) - current_offset;
}
int CallRuntimeDirectNode::compute_padding(int current_offset) const
{
return align_up(current_offset, alignment_required()) - current_offset;
}
int CallLeafDirectNode::compute_padding(int current_offset) const
{
return align_up(current_offset, alignment_required()) - current_offset;
}
int CallLeafDirectVectorNode::compute_padding(int current_offset) const
{
return align_up(current_offset, alignment_required()) - current_offset;
}
int CallLeafNoFPDirectNode::compute_padding(int current_offset) const
{
return align_up(current_offset, alignment_required()) - current_offset;
}
//=============================================================================
#ifndef PRODUCT
@@ -1326,7 +1306,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
}
//=============================================================================
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY;
const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty;
int ConstantTable::calculate_table_base_offset() const {
return 0; // absolute addressing, no offset
@@ -2104,10 +2084,10 @@ uint Matcher::int_pressure_limit()
// as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip
// derived pointers and lastly fail to spill after reaching maximum
// number of iterations. Lowering the default pressure threshold to
// (_NO_SPECIAL_REG32_mask.size() minus 1) forces CallNode to become
// (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become
// a high register pressure area of the code so that split_DEF can
// generate DefinitionSpillCopy for the derived pointer.
uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.size() - 1;
uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1;
if (!PreserveFramePointer) {
// When PreserveFramePointer is off, frame pointer is allocatable,
// but different from other SOC registers, it is excluded from
@@ -2122,7 +2102,7 @@ uint Matcher::int_pressure_limit()
uint Matcher::float_pressure_limit()
{
// _FLOAT_REG_mask is generated by adlc from the float_reg register class.
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE;
}
bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) {
@@ -2152,6 +2132,10 @@ RegMask Matcher::modL_proj_mask() {
return RegMask();
}
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return FP_REG_mask();
}
bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
assert_cond(addp != nullptr);
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
@@ -8191,7 +8175,7 @@ instruct unnecessary_membar_volatile_rvtso() %{
ins_cost(0);
size(0);
format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %}
ins_encode %{
__ block_comment("unnecessary_membar_volatile_rvtso");
@@ -10525,7 +10509,6 @@ instruct CallRuntimeDirect(method meth)
ins_encode(riscv_enc_java_to_runtime(meth));
ins_pipe(pipe_class_call);
ins_alignment(4);
%}
// Call Runtime Instruction
@@ -10543,7 +10526,6 @@ instruct CallLeafDirect(method meth)
ins_encode(riscv_enc_java_to_runtime(meth));
ins_pipe(pipe_class_call);
ins_alignment(4);
%}
// Call Runtime Instruction without safepoint and with vector arguments
@@ -10561,7 +10543,6 @@ instruct CallLeafDirectVector(method meth)
ins_encode(riscv_enc_java_to_runtime(meth));
ins_pipe(pipe_class_call);
ins_alignment(4);
%}
// Call Runtime Instruction
@@ -10579,7 +10560,6 @@ instruct CallLeafNoFPDirect(method meth)
ins_encode(riscv_enc_java_to_runtime(meth));
ins_pipe(pipe_class_call);
ins_alignment(4);
%}
// ============================================================================
@@ -10991,7 +10971,6 @@ instruct arrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI ba
iRegLNoSp tmp3, iRegLNoSp tmp4,
iRegLNoSp tmp5, iRegLNoSp tmp6, rFlagsReg cr)
%{
predicate(!UseRVV);
match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6,
USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr);
-22
View File
@@ -4080,28 +4080,6 @@ instruct varray_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result,
ins_pipe(pipe_class_memory);
%}
// fast ArraysSupport.vectorizedHashCode
instruct varrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI basic_type,
vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5,
vReg_V6 v6, vReg_V7 v7, vReg_V8 v8, vReg_V9 v9,
iRegLNoSp tmp1, iRegLNoSp tmp2, iRegLNoSp tmp3,
rFlagsReg cr)
%{
predicate(UseRVV);
match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
effect(USE_KILL ary, USE_KILL cnt, USE basic_type,
TEMP v2, TEMP v3, TEMP v4, TEMP v5, TEMP v6, TEMP v7, TEMP v8, TEMP v9,
TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result // KILL all" %}
ins_encode %{
__ arrays_hashcode_v($ary$$Register, $cnt$$Register, $result$$Register,
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
(BasicType)$basic_type$$constant);
%}
ins_pipe(pipe_class_memory);
%}
instruct vstring_compareU_128b(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
iRegI_R10 result, vReg_V4 v4, vReg_V5 v5, vReg_V6 v6, vReg_V7 v7,
vReg_V8 v8, vReg_V9 v9, vReg_V10 v10, vReg_V11 v11,
+72 -44
View File
@@ -885,8 +885,11 @@ static void fill_continuation_entry(MacroAssembler* masm) {
__ ld(t0, Address(xthread, JavaThread::cont_fastpath_offset()));
__ sd(t0, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
__ ld(t0, Address(xthread, JavaThread::held_monitor_count_offset()));
__ sd(t0, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
__ sd(zr, Address(xthread, JavaThread::cont_fastpath_offset()));
__ sd(zr, Address(xthread, JavaThread::held_monitor_count_offset()));
}
// on entry, sp points to the ContinuationEntry
@@ -902,6 +905,50 @@ static void continuation_enter_cleanup(MacroAssembler* masm) {
__ ld(t0, Address(sp, ContinuationEntry::parent_cont_fastpath_offset()));
__ sd(t0, Address(xthread, JavaThread::cont_fastpath_offset()));
if (CheckJNICalls) {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ lwu(t0, Address(sp, ContinuationEntry::flags_offset()));
__ beqz(t0, L_skip_vthread_code);
// If the held monitor count is > 0 and this vthread is terminating then
// it failed to release a JNI monitor. So we issue the same log message
// that JavaThread::exit does.
__ ld(t0, Address(xthread, JavaThread::jni_monitor_count_offset()));
__ beqz(t0, L_skip_vthread_code);
// Save return value potentially containing the exception oop in callee-saved x9
__ mv(x9, x10);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held));
// Restore potential return value
__ mv(x10, x9);
// For vthreads we have to explicitly zero the JNI monitor count of the carrier
// on termination. The held count is implicitly zeroed below when we restore from
// the parent held count (which has to be zero).
__ sd(zr, Address(xthread, JavaThread::jni_monitor_count_offset()));
__ bind(L_skip_vthread_code);
}
#ifdef ASSERT
else {
// Check if this is a virtual thread continuation
Label L_skip_vthread_code;
__ lwu(t0, Address(sp, ContinuationEntry::flags_offset()));
__ beqz(t0, L_skip_vthread_code);
// See comment just above. If not checking JNI calls the JNI count is only
// needed for assertion checking.
__ sd(zr, Address(xthread, JavaThread::jni_monitor_count_offset()));
__ bind(L_skip_vthread_code);
}
#endif
__ ld(t0, Address(sp, ContinuationEntry::parent_held_monitor_count_offset()));
__ sd(t0, Address(xthread, JavaThread::held_monitor_count_offset()));
__ ld(t0, Address(sp, ContinuationEntry::parent_offset()));
__ sd(t0, Address(xthread, JavaThread::cont_entry_offset()));
__ add(fp, sp, (int)ContinuationEntry::size() + 2 * wordSize /* 2 extra words to match up with leave() */);
@@ -955,23 +1002,20 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ bnez(c_rarg2, call_thaw);
address call_pc;
{
Assembler::IncompressibleScope scope(masm);
// Make sure the call is patchable
__ align(NativeInstruction::instruction_size);
// Make sure the call is patchable
__ align(NativeInstruction::instruction_size);
call_pc = __ reloc_call(resolve);
if (call_pc == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
oop_maps->add_gc_map(__ pc() - start, map);
__ post_call_nop();
const address tr_call = __ reloc_call(resolve);
if (tr_call == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
oop_maps->add_gc_map(__ pc() - start, map);
__ post_call_nop();
__ j(exit);
address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc);
address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -990,36 +1034,26 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ bnez(c_rarg2, call_thaw);
address call_pc;
{
Assembler::IncompressibleScope scope(masm);
// Make sure the call is patchable
__ align(NativeInstruction::instruction_size);
// Make sure the call is patchable
__ align(NativeInstruction::instruction_size);
call_pc = __ reloc_call(resolve);
if (call_pc == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
oop_maps->add_gc_map(__ pc() - start, map);
__ post_call_nop();
const address tr_call = __ reloc_call(resolve);
if (tr_call == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
oop_maps->add_gc_map(__ pc() - start, map);
__ post_call_nop();
__ j(exit);
__ bind(call_thaw);
// Post call nops must be natural aligned due to cmodx rules.
{
Assembler::IncompressibleScope scope(masm);
__ align(NativeInstruction::instruction_size);
ContinuationEntry::_thaw_call_pc_offset = __ pc() - start;
__ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw()));
oop_maps->add_gc_map(__ pc() - start, map->deep_copy());
ContinuationEntry::_return_pc_offset = __ pc() - start;
__ post_call_nop();
}
ContinuationEntry::_thaw_call_pc_offset = __ pc() - start;
__ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw()));
oop_maps->add_gc_map(__ pc() - start, map->deep_copy());
ContinuationEntry::_return_pc_offset = __ pc() - start;
__ post_call_nop();
__ bind(exit);
ContinuationEntry::_cleanup_offset = __ pc() - start;
@@ -1048,7 +1082,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
__ jr(x11); // the exception handler
}
address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc);
address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call);
if (stub == nullptr) {
fatal("CodeCache is full at gen_continuation_enter");
}
@@ -1081,16 +1115,10 @@ static void gen_continuation_yield(MacroAssembler* masm,
__ mv(c_rarg1, sp);
// Post call nops must be natural aligned due to cmodx rules.
__ align(NativeInstruction::instruction_size);
frame_complete = __ pc() - start;
address the_pc = __ pc();
{
Assembler::IncompressibleScope scope(masm);
__ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup
}
__ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup
__ mv(c_rarg0, xthread);
__ set_last_Java_frame(sp, fp, the_pc, t0);
@@ -73,9 +73,6 @@
do_stub(compiler, string_indexof_linear_ul) \
do_arch_entry(riscv, compiler, string_indexof_linear_ul, \
string_indexof_linear_ul, string_indexof_linear_ul) \
do_stub(compiler, arrays_hashcode_powers_of_31) \
do_arch_entry(riscv, compiler, arrays_hashcode_powers_of_31, \
arrays_hashcode_powers_of_31, arrays_hashcode_powers_of_31) \
#define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub, \
@@ -6624,24 +6624,6 @@ static const int64_t right_3_bits = right_n_bits(3);
return start;
}
address generate_arrays_hashcode_powers_of_31() {
assert(UseRVV, "sanity");
const int lmul = 2;
const int stride = MaxVectorSize / sizeof(jint) * lmul;
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "arrays_hashcode_powers_of_31");
address start = __ pc();
for (int i = stride; i >= 0; i--) {
jint power_of_31 = 1;
for (int j = i; j > 0; j--) {
power_of_31 = java_multiply(power_of_31, 31);
}
__ emit_int32(power_of_31);
}
return start;
}
#endif // COMPILER2
/**
@@ -6836,10 +6818,6 @@ static const int64_t right_3_bits = right_n_bits(3);
StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift();
}
if (UseVectorizedHashCodeIntrinsic && UseRVV) {
StubRoutines::riscv::_arrays_hashcode_powers_of_31 = generate_arrays_hashcode_powers_of_31();
}
if (UseSHA256Intrinsics) {
Sha2Generator sha2(_masm, this);
StubRoutines::_sha256_implCompress = sha2.generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id);
+19 -43
View File
@@ -133,7 +133,6 @@ Address TemplateTable::at_bcp(int offset) {
void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
Register temp_reg, bool load_bc_into_bc_reg /*=true*/,
int byte_no) {
assert_different_registers(bc_reg, temp_reg);
if (!RewriteBytecodes) { return; }
Label L_patch_done;
@@ -197,11 +196,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
__ bind(L_okay);
#endif
// Patch bytecode with release store to coordinate with ResolvedFieldEntry loads
// in fast bytecode codelets. load_field_entry has a memory barrier that gains
// the needed ordering, together with control dependency on entering the fast codelet
// itself.
__ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore);
// patch bytecode
__ sb(bc_reg, at_bcp(0));
__ bind(L_patch_done);
}
@@ -2173,7 +2168,7 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
assert_different_registers(Rcache, index, temp);
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
Label L_clinit_barrier_slow, L_done;
Label resolved, clinit_barrier_slow;
Bytecodes::Code code = bytecode();
__ load_method_entry(Rcache, index);
@@ -2190,20 +2185,12 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
__ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
__ mv(t0, (int) code);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
__ bne(temp, t0, L_clinit_barrier_slow); // have we resolved this bytecode?
__ ld(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(temp, temp);
__ clinit_barrier(temp, t0, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ beq(temp, t0, L_done); // have we resolved this bytecode?
}
__ beq(temp, t0, resolved); // have we resolved this bytecode?
// resolve first time through
// Class initialization barrier slow path lands here as well.
__ bind(clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ mv(temp, (int) code);
__ call_VM(noreg, entry, temp);
@@ -2212,7 +2199,14 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
__ load_method_entry(Rcache, index);
// n.b. unlike x86 Rcache is now rcpool plus the indexed offset
// so all clients ofthis method must be modified accordingly
__ bind(L_done);
__ bind(resolved);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
__ ld(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(temp, temp);
__ clinit_barrier(temp, t0, nullptr, &clinit_barrier_slow);
}
}
void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
@@ -2221,13 +2215,13 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
const Register temp = x9;
assert_different_registers(Rcache, index, temp);
Label L_clinit_barrier_slow, L_done;
Label resolved;
Bytecodes::Code code = bytecode();
switch (code) {
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
default: break;
case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
default: break;
}
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
@@ -2241,29 +2235,16 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
__ lbu(temp, Address(temp, 0));
__ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
__ mv(t0, (int) code); // have we resolved this bytecode?
// Class initialization barrier for static fields
if (VM_Version::supports_fast_class_init_checks() &&
(bytecode() == Bytecodes::_getstatic || bytecode() == Bytecodes::_putstatic)) {
const Register field_holder = temp;
__ bne(temp, t0, L_clinit_barrier_slow);
__ ld(field_holder, Address(Rcache, in_bytes(ResolvedFieldEntry::field_holder_offset())));
__ clinit_barrier(field_holder, t0, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ beq(temp, t0, L_done);
}
__ beq(temp, t0, resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ mv(temp, (int) code);
__ call_VM(noreg, entry, temp);
// Update registers with resolved info
__ load_field_entry(Rcache, index);
__ bind(L_done);
__ bind(resolved);
}
void TemplateTable::load_resolved_field_entry(Register obj,
@@ -3033,7 +3014,6 @@ void TemplateTable::fast_storefield(TosState state) {
// X11: field offset, X12: field holder, X13: flags
load_resolved_field_entry(x12, x12, noreg, x11, x13);
__ verify_field_offset(x11);
{
Label notVolatile;
@@ -3121,8 +3101,6 @@ void TemplateTable::fast_accessfield(TosState state) {
__ load_field_entry(x12, x11);
__ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
__ verify_field_offset(x11);
__ load_unsigned_byte(x13, Address(x12, in_bytes(ResolvedFieldEntry::flags_offset())));
// x10: object
@@ -3178,9 +3156,7 @@ void TemplateTable::fast_xaccess(TosState state) {
__ ld(x10, aaddress(0));
// access constant pool cache
__ load_field_entry(x12, x13, 2);
__ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/);
__ verify_field_offset(x11);
// make sure exception is reported in correct bcp range (getfield is
// next instruction)
+61 -106
View File
@@ -24,14 +24,9 @@
*
*/
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "classfile/vmIntrinsics.hpp"
#include "code/codeBlob.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/os.inline.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/formatBuffer.hpp"
#include "utilities/macros.hpp"
@@ -39,72 +34,21 @@
#include <ctype.h>
uint32_t VM_Version::_initial_vector_length = 0;
address VM_Version::_misaligned_vector_fault_pc1 = nullptr;
address VM_Version::_misaligned_vector_fault_pc2 = nullptr;
address VM_Version::_misaligned_vector_continuation_pc = nullptr;
short short_array[4] = { 0, 0, 0, 0 };
static BufferBlob* stub_blob;
static const int stub_size = 256;
extern "C" {
typedef int (*detect_misaligned_vector_stub_t)();
}
static detect_misaligned_vector_stub_t detect_misaligned_vector_stub = nullptr;
class VM_Version_StubGenerator: public StubCodeGenerator {
public:
VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
~VM_Version_StubGenerator() {}
address generate_detect_misaligned_vector(address* fault_pc1, address* fault_pc2, address* continuation_pc) {
StubCodeMark mark(this, "VM_Version", "detect_misaligned_vector_stub");
# define __ _masm->
address start = __ pc();
__ enter();
__ mv(x10, zr);
__ la(t1, ExternalAddress((address) short_array));
__ addi(t1, t1, 1); // Misaligned address
__ vsetivli(x0, 1, Assembler::e16);
__ vmv_s_x(v2, zr);
__ addi(t2, zr, 1);
__ vmv_s_x(v1, t2);
*fault_pc1 = __ pc();
__ vse16_v(v1, t1); // Misaligned vector store
*fault_pc2 = __ pc();
__ vle16_v(v2, t1); // Misaligned vector load
*continuation_pc = __ pc();
__ vmv_x_s(x10, v2);
__ leave();
__ ret();
# undef __
return start;
}
};
#define DEF_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::ext_##PRETTY##RVExtFeatureValue VM_Version::ext_##PRETTY;
#define DEF_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::NAME##RVExtFeatureValue VM_Version::NAME;
RV_EXT_FEATURE_FLAGS(DEF_RV_EXT_FEATURE)
#undef DEF_RV_EXT_FEATURE
#define DEF_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::PRETTY##RVNonExtFeatureValue VM_Version::PRETTY;
#define DEF_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::NAME##RVNonExtFeatureValue VM_Version::NAME;
RV_NON_EXT_FEATURE_FLAGS(DEF_RV_NON_EXT_FEATURE)
#undef DEF_RV_NON_EXT_FEATURE
#define ADD_RV_EXT_FEATURE_IN_LIST(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::ext_##PRETTY,
#define ADD_RV_NON_EXT_FEATURE_IN_LIST(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::PRETTY,
#define ADD_RV_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::NAME,
#define ADD_RV_NON_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::NAME,
VM_Version::RVFeatureValue* VM_Version::_feature_list[] = {
RV_EXT_FEATURE_FLAGS(ADD_RV_EXT_FEATURE_IN_LIST)
RV_NON_EXT_FEATURE_FLAGS(ADD_RV_NON_EXT_FEATURE_IN_LIST)
@@ -159,6 +103,17 @@ void VM_Version::common_initialize() {
useRVA23U64Profile();
}
// Enable vendor specific features
if (mvendorid.enabled()) {
// Rivos
if (mvendorid.value() == RIVOS) {
if (FLAG_IS_DEFAULT(UseConservativeFence)) {
FLAG_SET_DEFAULT(UseConservativeFence, false);
}
}
}
if (UseZic64b) {
if (CacheLineSize != 64) {
assert(!FLAG_IS_DEFAULT(CacheLineSize), "default cache line size should be 64 bytes");
@@ -193,7 +148,7 @@ void VM_Version::common_initialize() {
FLAG_SET_DEFAULT(UseSignumIntrinsic, true);
}
if (UseRVC && !ext_c.enabled()) {
if (UseRVC && !ext_C.enabled()) {
warning("RVC is not supported on this CPU");
FLAG_SET_DEFAULT(UseRVC, false);
@@ -223,25 +178,9 @@ void VM_Version::common_initialize() {
(unaligned_scalar.value() == MISALIGNED_SCALAR_FAST));
}
if (UseRVV) {
// The hwprobe syscall won't be able to detect support for misaligned vector accesses on old kernels.
// Resort to detect_misaligned_vector_support() to see if misaligned vector accesses may trap or not.
if (!unaligned_vector.enabled()) {
if (AlignVector == false && !VM_Version::detect_misaligned_vector_support()) {
warning("Misaligned vector accesses are not supported on this CPU");
FLAG_SET_DEFAULT(AlignVector, true);
}
} else {
if (FLAG_IS_DEFAULT(AlignVector)) {
FLAG_SET_DEFAULT(AlignVector,
unaligned_vector.value() != MISALIGNED_VECTOR_FAST);
} else if (AlignVector == false) {
if (unaligned_vector.value() != MISALIGNED_VECTOR_FAST) {
warning("Misaligned vector accesses are not supported on this CPU");
FLAG_SET_DEFAULT(AlignVector, true);
}
}
}
if (FLAG_IS_DEFAULT(AlignVector) && unaligned_vector.enabled()) {
FLAG_SET_DEFAULT(AlignVector,
unaligned_vector.value() != MISALIGNED_VECTOR_FAST);
}
#ifdef __riscv_ztso
@@ -260,7 +199,7 @@ void VM_Version::common_initialize() {
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
}
if (UseZicboz && zicboz_block_size.value() > 0) {
if (UseZicboz && zicboz_block_size.enabled() && zicboz_block_size.value() > 0) {
assert(is_power_of_2(zicboz_block_size.value()), "Sanity");
if (FLAG_IS_DEFAULT(UseBlockZeroing)) {
FLAG_SET_DEFAULT(UseBlockZeroing, true);
@@ -274,8 +213,13 @@ void VM_Version::common_initialize() {
}
if (UseRVV) {
// read vector length from vector CSR vlenb
_initial_vector_length = cpu_vector_length();
if (!ext_V.enabled() && FLAG_IS_DEFAULT(UseRVV)) {
warning("RVV is not supported on this CPU");
FLAG_SET_DEFAULT(UseRVV, false);
} else {
// read vector length from vector CSR vlenb
_initial_vector_length = cpu_vector_length();
}
}
// Misc Intrinsics that could depend on RVV.
@@ -295,6 +239,36 @@ void VM_Version::common_initialize() {
warning("CRC32C intrinsics are not available on this CPU.");
FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false);
}
// UseZvbb (depends on RVV).
if (UseZvbb && !UseRVV) {
warning("Cannot enable UseZvbb on cpu without RVV support.");
FLAG_SET_DEFAULT(UseZvbb, false);
}
// UseZvbc (depends on RVV).
if (UseZvbc && !UseRVV) {
warning("Cannot enable UseZvbc on cpu without RVV support.");
FLAG_SET_DEFAULT(UseZvbc, false);
}
// UseZvkn (depends on RVV).
if (UseZvkn && !UseRVV) {
warning("Cannot enable UseZvkn on cpu without RVV support.");
FLAG_SET_DEFAULT(UseZvkn, false);
}
// UseZvfh (depends on RVV)
if (UseZvfh) {
if (!UseRVV) {
warning("Cannot enable UseZvfh on cpu without RVV support.");
FLAG_SET_DEFAULT(UseZvfh, false);
}
if (!UseZfh) {
warning("Cannot enable UseZvfh on cpu without Zfh support.");
FLAG_SET_DEFAULT(UseZvfh, false);
}
}
}
#ifdef COMPILER2
@@ -553,22 +527,3 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) {
}
return true;
}
bool VM_Version::detect_misaligned_vector_support() {
ResourceMark rm;
stub_blob = BufferBlob::create("detect_misaligned_vector_stub", stub_size);
if (stub_blob == nullptr) {
vm_exit_during_initialization("Unable to allocate detect_misaligned_vector_stub");
}
CodeBuffer c(stub_blob);
VM_Version_StubGenerator g(&c);
detect_misaligned_vector_stub = CAST_TO_FN_PTR(detect_misaligned_vector_stub_t,
g.generate_detect_misaligned_vector(
&VM_Version::_misaligned_vector_fault_pc1,
&VM_Version::_misaligned_vector_fault_pc2,
&VM_Version::_misaligned_vector_continuation_pc));
return detect_misaligned_vector_stub() == 1;
}
+141 -214
View File
@@ -52,19 +52,24 @@ class VM_Version : public Abstract_VM_Version {
const char* const _pretty;
const bool _feature_string;
const uint64_t _linux_feature_bit;
int64_t _value;
public:
RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
_pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)) {
_pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)),
_value(-1) {
}
virtual void enable_feature(int64_t value = 0) {
_value = value;
}
virtual void disable_feature() {
_value = -1;
}
virtual void enable_feature(int64_t value = 0) = 0;
virtual void disable_feature() = 0;
const char* pretty() { return _pretty; }
uint64_t feature_bit() { return _linux_feature_bit; }
bool feature_string() { return _feature_string; }
int64_t value() { return _value; }
virtual bool enabled() = 0;
virtual void update_flag() = 0;
virtual void log_enabled() = 0;
};
#define UPDATE_DEFAULT(flag) \
@@ -80,35 +85,27 @@ class VM_Version : public Abstract_VM_Version {
} \
} \
#define UPDATE_DEFAULT_DEP(flag, dep0, ...) \
void update_flag() { \
assert(enabled(), "Must be."); \
DEBUG_ONLY(verify_deps(dep0, ##__VA_ARGS__)); \
if (FLAG_IS_DEFAULT(flag)) { \
if (deps_all_enabled(dep0, ##__VA_ARGS__)) { \
FLAG_SET_DEFAULT(flag, true); \
} else { \
FLAG_SET_DEFAULT(flag, false); \
stringStream ss; \
deps_string(ss, dep0, ##__VA_ARGS__); \
warning("Cannot enable " #flag ", it's missing dependent extension(s) %s", ss.as_string(true)); \
/* Sync CPU features with flags */ \
disable_feature(); \
} \
} else { \
/* Sync CPU features with flags */ \
if (!flag) { \
disable_feature(); \
} else if (!deps_all_enabled(dep0, ##__VA_ARGS__)) { \
FLAG_SET_DEFAULT(flag, false); \
stringStream ss; \
deps_string(ss, dep0, ##__VA_ARGS__); \
warning("Cannot enable " #flag ", it's missing dependent extension(s) %s", ss.as_string(true)); \
/* Sync CPU features with flags */ \
disable_feature(); \
} \
} \
} \
#define UPDATE_DEFAULT_DEP(flag, dep) \
void update_flag() { \
assert(enabled(), "Must be."); \
/* dep must be declared before */ \
assert((uintptr_t)(this) > \
(uintptr_t)(&dep), "Invalid"); \
if (FLAG_IS_DEFAULT(flag)) { \
if (dep.enabled()) { \
FLAG_SET_DEFAULT(flag, true); \
} else { \
FLAG_SET_DEFAULT(flag, false); \
/* Sync CPU features with flags */ \
disable_feature(); \
} \
} else { \
/* Sync CPU features with flags */ \
if (!flag) { \
disable_feature(); \
} \
} \
} \
#define NO_UPDATE_DEFAULT \
void update_flag() {} \
@@ -116,98 +113,88 @@ class VM_Version : public Abstract_VM_Version {
class RVExtFeatureValue : public RVFeatureValue {
const uint32_t _cpu_feature_index;
public:
RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) :
RVFeatureValue(pretty, linux_bit_num, fstring),
_cpu_feature_index(cpu_feature_index) {
}
int cpu_feature_index() {
// Can be used to check, for example, v is declared before Zvfh in RV_EXT_FEATURE_FLAGS.
return _cpu_feature_index;
}
bool enabled() {
return RVExtFeatures::current()->support_feature(_cpu_feature_index);
}
void enable_feature(int64_t value = 0) {
RVFeatureValue::enable_feature(value);
RVExtFeatures::current()->set_feature(_cpu_feature_index);
}
void disable_feature() {
RVFeatureValue::disable_feature();
RVExtFeatures::current()->clear_feature(_cpu_feature_index);
}
void log_enabled();
protected:
bool deps_all_enabled(RVExtFeatureValue* dep0, ...) {
assert(dep0 != nullptr, "must not");
va_list va;
va_start(va, dep0);
RVExtFeatureValue* next = dep0;
bool enabled = true;
while (next != nullptr && enabled) {
enabled = next->enabled();
next = va_arg(va, RVExtFeatureValue*);
}
va_end(va);
return enabled;
}
void deps_string(stringStream& ss, RVExtFeatureValue* dep0, ...) {
assert(dep0 != nullptr, "must not");
ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled");
va_list va;
va_start(va, dep0);
RVExtFeatureValue* next = nullptr;
while ((next = va_arg(va, RVExtFeatureValue*)) != nullptr) {
ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled");
}
va_end(va);
}
#ifdef ASSERT
void verify_deps(RVExtFeatureValue* dep0, ...) {
assert(dep0 != nullptr, "must not");
assert(cpu_feature_index() >= 0, "must");
va_list va;
va_start(va, dep0);
RVExtFeatureValue* next = dep0;
while (next != nullptr) {
assert(next->cpu_feature_index() >= 0, "must");
// We only need to check depenency relationship for extension flags.
// The dependant ones must be declared before this, for example, v must be declared
// before Zvfh in RV_EXT_FEATURE_FLAGS. The reason is in setup_cpu_available_features
// we need to make sure v is `update_flag`ed before Zvfh, so Zvfh is `update_flag`ed
// based on v.
assert(cpu_feature_index() > next->cpu_feature_index(), "Invalid");
next = va_arg(va, RVExtFeatureValue*);
}
va_end(va);
}
#endif // ASSERT
};
class RVNonExtFeatureValue : public RVFeatureValue {
static const int64_t DEFAULT_VALUE = -1;
int64_t _value;
bool _enabled;
public:
RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
RVFeatureValue(pretty, linux_bit_num, fstring),
_value(DEFAULT_VALUE) {
_enabled(false) {
}
bool enabled() { return _value != DEFAULT_VALUE; }
void enable_feature(int64_t value) {
assert(value != DEFAULT_VALUE, "Sanity");
_value = value;
bool enabled() { return _enabled; }
void enable_feature(int64_t value = 0) {
RVFeatureValue::enable_feature(value);
_enabled = true;
}
void disable_feature() {
RVFeatureValue::disable_feature();
_enabled = false;
}
void disable_feature() { _value = DEFAULT_VALUE; }
int64_t value() { return _value; }
void log_enabled();
};
// Frozen standard extensions
// I RV64I
// M Integer Multiplication and Division
// A Atomic Instructions
// F Single-Precision Floating-Point
// D Single-Precision Floating-Point
// (G = M + A + F + D)
// Q Quad-Precision Floating-Point
// C Compressed Instructions
// H Hypervisor
//
// Others, open and non-standard
// V Vector
//
// Cache Management Operations
// Zicbom Cache Block Management Operations
// Zicboz Cache Block Zero Operations
// Zicbop Cache Block Prefetch Operations
//
// Bit-manipulation
// Zba Address generation instructions
// Zbb Basic bit-manipulation
// Zbc Carry-less multiplication
// Zbs Single-bit instructions
//
// Zfh Half-Precision Floating-Point instructions
// Zfhmin Minimal Half-Precision Floating-Point instructions
//
// Zicond Conditional operations
//
// Zicsr Control and Status Register (CSR) Instructions
// Zifencei Instruction-Fetch Fence
// Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space.
// Zihintpause Pause instruction HINT
//
// Zc Code Size Reduction - Additional compressed instructions.
// Zcb Simple code-size saving instructions
//
// Other features and settings
// mvendorid Manufactory JEDEC id encoded, ISA vol 2 3.1.2..
// marchid Id for microarch. Mvendorid plus marchid uniquely identify the microarch.
// mimpid A unique encoding of the version of the processor implementation.
// unaligned_scalar Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported)
// unaligned_vector Performance of misaligned vector accesses (unknown, unspported, slow, fast)
// satp mode SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64
public:
#define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord
@@ -217,83 +204,47 @@ 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)) \
decl(ext_I , i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_M , m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_A , a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_F , f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_D , d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_C , c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
decl(ext_Q , q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_H , h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_V , v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
decl(ext_Zicbom , Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
decl(ext_Zicboz , Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
decl(ext_Zicbop , Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
decl(ext_Zba , Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
decl(ext_Zbb , Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
decl(ext_Zbkb , Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
decl(ext_Zcb , Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
decl(ext_Zfa , Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
decl(ext_Zfh , Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zfhmin , Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
decl(ext_Zicsr , Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zicntr , Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
decl(ext_Ztso , Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
decl(ext_Zihintpause , Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
decl(ext_Zacas , Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
decl(ext_Zvbb , Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \
decl(ext_Zvbc , Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \
decl(ext_Zvfh , Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \
decl(ext_Zvkn , Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \
decl(ext_Zicond , Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
#define DECLARE_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct ext_##PRETTY##RVExtFeatureValue : public RVExtFeatureValue { \
ext_##PRETTY##RVExtFeatureValue() : \
RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##ext_##PRETTY, FSTRING) {} \
FLAGF; \
}; \
static ext_##PRETTY##RVExtFeatureValue ext_##PRETTY; \
#define DECLARE_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct NAME##RVExtFeatureValue : public RVExtFeatureValue { \
NAME##RVExtFeatureValue() : \
RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##NAME, FSTRING) {} \
FLAGF; \
}; \
static NAME##RVExtFeatureValue NAME; \
RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE)
#undef DECLARE_RV_EXT_FEATURE
@@ -301,27 +252,21 @@ class VM_Version : public Abstract_VM_Version {
// Non-extension features
//
#define RV_NON_EXT_FEATURE_FLAGS(decl) \
/* Id for microarch. Mvendorid plus marchid uniquely identify the microarch. */ \
decl(marchid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
/* A unique encoding of the version of the processor implementation. */ \
decl(mimpid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
/* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \
decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
/* SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 */ \
decl(satp_mode , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
/* Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) */ \
decl(unaligned_scalar , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
/* Performance of misaligned vector accesses (unknown, unspported, slow, fast) */ \
decl(unaligned_vector , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(zicboz_block_size , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mvendorid , VendorId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(marchid , ArchId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mimpid , ImpId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(satp_mode , SATP , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(unaligned_scalar , UnalignedScalar , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(unaligned_vector , UnalignedVector , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(zicboz_block_size, ZicbozBlockSize , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
#define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct PRETTY##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
PRETTY##RVNonExtFeatureValue() : \
#define DECLARE_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct NAME##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
NAME##RVNonExtFeatureValue() : \
RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {} \
FLAGF; \
}; \
static PRETTY##RVNonExtFeatureValue PRETTY; \
static NAME##RVNonExtFeatureValue NAME; \
RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE)
#undef DECLARE_RV_NON_EXT_FEATURE
@@ -331,7 +276,7 @@ private:
class RVExtFeatures : public CHeapObj<mtCode> {
public:
enum RVFeatureIndex {
#define DECLARE_RV_FEATURE_ENUM(PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##ext_##PRETTY,
#define DECLARE_RV_FEATURE_ENUM(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##NAME,
RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM)
MAX_CPU_FEATURE_INDEX
@@ -502,21 +447,6 @@ private:
constexpr static bool supports_secondary_supers_table() { return true; }
static bool supports_misaligned_vector_accesses() { return !AlignVector; }
static bool is_misaligned_vector_fault(address pc) {
return pc != nullptr && (pc == _misaligned_vector_fault_pc1 || pc == _misaligned_vector_fault_pc2);
}
static address continuation_for_misaligned_vector_fault(address pc) {
assert(_misaligned_vector_continuation_pc != nullptr , "not initialized");
return _misaligned_vector_continuation_pc;
}
static address _misaligned_vector_fault_pc1;
static address _misaligned_vector_fault_pc2;
static address _misaligned_vector_continuation_pc;
static bool supports_on_spin_wait() { return UseZihintpause; }
// RISCV64 supports fast class initialization checks
@@ -529,9 +459,6 @@ private:
// Check intrinsic support
static bool is_intrinsic_supported(vmIntrinsicID id);
// Detect misaligned vector support
static bool detect_misaligned_vector_support();
};
#endif // CPU_RISCV_VM_VERSION_RISCV_HPP
@@ -282,6 +282,13 @@ LIR_Opr FrameMap::stack_pointer() {
return Z_SP_opr;
}
// JSR 292
// On ZARCH_64, there is no need to save the SP, because neither
// method handle intrinsics nor compiled lambda forms modify it.
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
return LIR_OprFact::illegalOpr;
}
bool FrameMap::validate_frame() {
return true;
}
+1 -1
View File
@@ -356,7 +356,7 @@ instruct g1CompareAndExchangeP(iRegP mem_ptr, rarg5RegP oldval, iRegP_N2P newval
__ z_lgr($res$$Register, $oldval$$Register); // previous content
__ z_csg($res$$Register, $newval$$Register, 0, $mem_ptr$$reg);
__ z_csg($oldval$$Register, $newval$$Register, 0, $mem_ptr$$reg);
write_barrier_post(masm, this,
$mem_ptr$$Register /* store_addr */,
+5
View File
@@ -1980,6 +1980,11 @@ RegMask Matcher::modL_proj_mask() {
return _Z_RARG3_LONG_REG_mask;
}
// Copied from sparc.
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
return RegMask();
}
// Should the matcher clone input 'm' of node 'n'?
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
if (is_encode_and_store_pattern(n, m)) {
+15 -31
View File
@@ -2360,7 +2360,7 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
assert_different_registers(Rcache, index);
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
Label L_clinit_barrier_slow, L_done;
Label resolved, clinit_barrier_slow;
Bytecodes::Code code = bytecode();
switch (code) {
@@ -2375,30 +2375,27 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
__ load_method_entry(Rcache, index);
__ z_cli(Address(Rcache, bc_offset), code);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
const Register method = Z_R1_scratch;
const Register klass = Z_R1_scratch;
__ z_brne(L_clinit_barrier_slow);
__ z_lg(method, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(klass, method);
__ clinit_barrier(klass, Z_thread, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ z_bre(L_done);
}
__ z_bre(resolved);
// Resolve first time through
// Class initialization barrier slow path lands here as well.
__ bind(clinit_barrier_slow);
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ load_const_optimized(Z_ARG2, (int)code);
__ call_VM(noreg, entry, Z_ARG2);
// Update registers with resolved info.
__ load_method_entry(Rcache, index);
__ bind(resolved);
__ bind(L_done);
// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
const Register method = Z_R1_scratch;
const Register klass = Z_R1_scratch;
__ z_lg(method, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset())));
__ load_method_holder(klass, method);
__ clinit_barrier(klass, Z_thread, nullptr /*L_fast_path*/, &clinit_barrier_slow);
}
BLOCK_COMMENT("} resolve_cache_and_index_for_method");
}
@@ -2411,7 +2408,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
assert_different_registers(cache, index);
assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
Label L_clinit_barrier_slow, L_done;
NearLabel resolved;
Bytecodes::Code code = bytecode();
switch (code) {
@@ -2425,22 +2422,9 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
in_bytes(ResolvedFieldEntry::put_code_offset()) ;
__ z_cli(Address(cache, code_offset), code);
// Class initialization barrier for static fields
if (VM_Version::supports_fast_class_init_checks() &&
(bytecode() == Bytecodes::_getstatic || bytecode() == Bytecodes::_putstatic)) {
const Register field_holder = index;
__ z_brne(L_clinit_barrier_slow);
__ load_sized_value(field_holder, Address(cache, ResolvedFieldEntry::field_holder_offset()), sizeof(void*), false);
__ clinit_barrier(field_holder, Z_thread, &L_done, /*L_slow_path*/ nullptr);
__ bind(L_clinit_barrier_slow);
} else {
__ z_bre(L_done);
}
__ z_bre(resolved);
// resolve first time through
// Class initialization barrier slow path lands here as well.
address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
__ load_const_optimized(Z_ARG2, (int)code);
__ call_VM(noreg, entry, Z_ARG2);
@@ -2448,7 +2432,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
// Update registers with resolved info.
__ load_field_entry(cache, index);
__ bind(L_done);
__ bind(resolved);
BLOCK_COMMENT("} resolve_cache_and_index_for_field");
}

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