Compare commits
358 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e1d857c5a9 | |||
| 928c3df421 | |||
| 344e3c66cc | |||
| 33eba42f71 | |||
| 2a2d65c631 | |||
| a5858ba50f | |||
| ea7186a87f | |||
| a0c4124432 | |||
| 2be273f20f | |||
| ec13c283c4 | |||
| 430041d366 | |||
| b6b0f051d5 | |||
| 2aa0efd425 | |||
| 634746a0f1 | |||
| 207fe55d90 | |||
| eee2908853 | |||
| 2de8d58552 | |||
| 0522cf2ed9 | |||
| c781a2ff31 | |||
| a1302e5fbc | |||
| a1be297911 | |||
| 257bb2b279 | |||
| dc6858f336 | |||
| c867971340 | |||
| 73923601d8 | |||
| ee353201d1 | |||
| 8c775e299d | |||
| f158451c25 | |||
| 5609ee11a2 | |||
| 39211e7fac | |||
| 2148dbbe75 | |||
| 7e068cc8d5 | |||
| 680414d0f9 | |||
| c2fde517b4 | |||
| eff6439e75 | |||
| b0af41d667 | |||
| 4625199358 | |||
| 181657084a | |||
| 926f61f2e3 | |||
| 49b17dd5c9 | |||
| 0cc88e4ad4 | |||
| 6cd7f30d8d | |||
| 0cb8ccd89a | |||
| 0103f21635 | |||
| a3e41ea6c6 | |||
| f84be36dd5 | |||
| 1e5e17a10a | |||
| 28bf9176b8 | |||
| cc6f8f1307 | |||
| b159ca097a | |||
| e8e2aadd9e | |||
| 0a97bef840 | |||
| e62a7fa383 | |||
| 9b9559a2e3 | |||
| a22438ddc5 | |||
| 46c23bb1a2 | |||
| 31beb7d3b3 | |||
| 55787fe5f5 | |||
| bd7315648f | |||
| 4d20f7696c | |||
| 0bdd6f0640 | |||
| 0c1c86e68e | |||
| 18fd047702 | |||
| 1392a0b460 | |||
| 3248aaf3c4 | |||
| 9589a29d25 | |||
| d4472979c4 | |||
| 844118a9d8 | |||
| d7b525ab99 | |||
| 873666d157 | |||
| 7e03240974 | |||
| e56db37734 | |||
| 95380e1ea5 | |||
| 87092ef1d9 | |||
| 303eb1096c | |||
| f2a998326a | |||
| 5dfe115ce1 | |||
| f475eb8ee7 | |||
| 1653999871 | |||
| 5fc3904bfe | |||
| ead35a754b | |||
| d6c122b3ff | |||
| 6e911d819e | |||
| b5b83247da | |||
| 17c13e53af | |||
| ff6a0170f0 | |||
| aed42a16ba | |||
| 7fe0665730 | |||
| aa194c6a5a | |||
| 5696d60663 | |||
| 0168687fc3 | |||
| 4ed364033d | |||
| a7a3a660e3 | |||
| c9cbd31f85 | |||
| bfe6937244 | |||
| 1bd814c3b2 | |||
| 784af438ef | |||
| 5191d72092 | |||
| 1af37e5c3f | |||
| 159452e85a | |||
| c53ab10dae | |||
| 9d11787799 | |||
| 112d88523d | |||
| 008d8d914c | |||
| 355cb45943 | |||
| 42b2999c31 | |||
| c82c892063 | |||
| 3d95c83b14 | |||
| 95def24b02 | |||
| 70528bd399 | |||
| ad2d04733b | |||
| 622a611c33 | |||
| 09e87971e8 | |||
| 65b8fe62b4 | |||
| d6537c6d3e | |||
| bbbb9c5f15 | |||
| 7ed93cf40e | |||
| 64ff7062c1 | |||
| 4b85ba9067 | |||
| 72663695da | |||
| 6d1529cd70 | |||
| 90cf3a2086 | |||
| 702179e785 | |||
| 4786f8bee5 | |||
| a3ee821f38 | |||
| 2eb0898fef | |||
| 5bf1bab5b3 | |||
| be0e49b7e2 | |||
| 449641813a | |||
| d6ca382f4e | |||
| 4ca4485e9a | |||
| 1d6cafdc52 | |||
| 9b1633ded0 | |||
| 8b1cf8eefe | |||
| 1668162319 | |||
| b83e7939dd | |||
| 551cd03b99 | |||
| f292d7c66c | |||
| 9feb8f21b5 | |||
| 0496806102 | |||
| d47e6b713c | |||
| d278043ddb | |||
| 62fa971f31 | |||
| 0db4702891 | |||
| 28460ca330 | |||
| 0af959a340 | |||
| 98e1d2fab1 | |||
| 4728f746a8 | |||
| 1605e8392e | |||
| a6f624b074 | |||
| 9b99bc8ef5 | |||
| 2dfe4586f7 | |||
| 7e29d294e5 | |||
| 376d77e8a7 | |||
| fc49a1b502 | |||
| f6d77cb332 | |||
| 5594d6bc88 | |||
| afda8ad460 | |||
| f52aed6f81 | |||
| d5a207994b | |||
| a1a37bd7b2 | |||
| 1159b53bfc | |||
| b00720edd7 | |||
| b6e5ef4ad0 | |||
| be10722436 | |||
| 5a32966d42 | |||
| f4209dff3b | |||
| 2311ec394d | |||
| 1873b45948 | |||
| 52b02edaba | |||
| d6e2d4eb1f | |||
| cd1ce5883d | |||
| 1cdd241ff3 | |||
| b73228b51c | |||
| 1992b69a47 | |||
| 501fa2041a | |||
| 37b725d9c1 | |||
| 7c75cb312c | |||
| 9891cd69e4 | |||
| 48d21b50fa | |||
| 13f460c395 | |||
| 233d3a8d43 | |||
| 005877b063 | |||
| dd410e0b77 | |||
| fd29677479 | |||
| 5bb9fed9de | |||
| 9def7bfea2 | |||
| 7e3e55a576 | |||
| 692c20ce1d | |||
| 285d16a3a3 | |||
| b37a1a33ae | |||
| f22e9493b0 | |||
| aa14d11137 | |||
| af2fbd5a71 | |||
| 991f8e6f38 | |||
| 1b11bea76b | |||
| 914b44e277 | |||
| 0b81db1d38 | |||
| 5873c4b5d6 | |||
| 0e5655e668 | |||
| 1aa62dcafd | |||
| 4d0da18ab6 | |||
| 92f2ab2e1b | |||
| ac73e688b1 | |||
| 79bcc7b8ec | |||
| 927aa3f8da | |||
| 23fcbb0bad | |||
| c12f0e74a9 | |||
| 6a4c2676a6 | |||
| c66950643e | |||
| d45e65bab4 | |||
| f58e17fd27 | |||
| d27649fe22 | |||
| bd25db1fb8 | |||
| 862119565d | |||
| 2ac24bf1ba | |||
| 650fd35b3b | |||
| 4ee6079b11 | |||
| 910bb68e51 | |||
| 6bfd018bea | |||
| 7f070d356c | |||
| 6b3162620b | |||
| 1ea8cfa6dc | |||
| ebeb77baae | |||
| 4ca3ab6275 | |||
| eb835e05f9 | |||
| eb729f0aaa | |||
| 8a20656ed0 | |||
| 0f2a95c15d | |||
| a9c93f865b | |||
| 4b4d0cd35a | |||
| 9c46febcac | |||
| 6bec42adcc | |||
| aed9485bbb | |||
| c06d6805aa | |||
| 07549f3e15 | |||
| e783c524c1 | |||
| eb34a11793 | |||
| 2376a9e972 | |||
| 0f406c420e | |||
| 596af0a7cc | |||
| b6a4cfecb7 | |||
| e3320a9df5 | |||
| 2bfada3f58 | |||
| 2c114d676d | |||
| baf8bc5701 | |||
| 59e87437b4 | |||
| e6781fd949 | |||
| 069c569a71 | |||
| 85877e2022 | |||
| ba7bf43c76 | |||
| 5d9f94e05e | |||
| f740cd2aad | |||
| 76dba201fa | |||
| c3fbbfabcc | |||
| e6868c6248 | |||
| 837f634bf2 | |||
| 012e079d11 | |||
| 0e98ec3662 | |||
| 0935b76c6b | |||
| aee73d3568 | |||
| 23a65644ae | |||
| f81c7c592b | |||
| 7231916754 | |||
| 134b63f0e8 | |||
| 2e783963d2 | |||
| ebb6fd7d78 | |||
| 3790965df3 | |||
| f62b9eca08 | |||
| 854b384b12 | |||
| da7121aff9 | |||
| fa6e884105 | |||
| 3f27a03bba | |||
| 1d55adee11 | |||
| 3d113af9e3 | |||
| 5fccabff15 | |||
| 1a03a1fbb1 | |||
| 7ad9bdef1e | |||
| 5252262349 | |||
| 2c7f7380ea | |||
| 56baf64ada | |||
| cc563c87cd | |||
| 8be16160d2 | |||
| dfd383224d | |||
| 5251405ce9 | |||
| fa3af820ad | |||
| 4df41d2a75 | |||
| db6320df98 | |||
| ef724f40c1 | |||
| 6b72b77803 | |||
| e44ef0c32b | |||
| c54dcefbfd | |||
| 182fbc2b83 | |||
| c69456e87a | |||
| 3607e9986f | |||
| 5a2700f231 | |||
| 84e5d63b9f | |||
| f49849a5ed | |||
| 6c2d383492 | |||
| 1188ca55f5 | |||
| 394eb80a48 | |||
| 8c3ca024c7 | |||
| 17d8fa8e42 | |||
| 0366d8823b | |||
| 9b02896b47 | |||
| fe9dbcc496 | |||
| 07ecc93dbd | |||
| 6b4b10200e | |||
| 8cc54ec6b8 | |||
| 07ea907e4f | |||
| 444007fc23 | |||
| 8606d3f840 | |||
| 64c46d8efc | |||
| ba0a6eed1a | |||
| b19e872192 | |||
| aea71ccab7 | |||
| 586167cff5 | |||
| c0a4c0ba97 | |||
| 2746c1a555 | |||
| 89af6e13f2 | |||
| a36d5f8fa9 | |||
| 538a722c2e | |||
| c57003c9b8 | |||
| 2f29b3f24a | |||
| 59e76af47b | |||
| 6c8e384c63 | |||
| 3d97e17a31 | |||
| aabf699dd0 | |||
| 9d71af108e | |||
| 63688d894e | |||
| 9d9c0e0670 | |||
| fdbba049a2 | |||
| 6165921449 | |||
| 08b677bba4 | |||
| 75269fdb49 | |||
| d53190ac44 | |||
| e19ec6f785 | |||
| 320230db5f | |||
| af8fb20ac0 | |||
| 9093d3a04c | |||
| 5b1ebbb271 | |||
| 37f0e74d32 | |||
| cedc0117ac | |||
| 12c0f29b97 | |||
| c6cecc581f | |||
| 62cc347242 | |||
| 556dfddac8 | |||
| bdf6853cfd | |||
| aa6ff45052 | |||
| 25abdd85c4 | |||
| 501b2b3ebc | |||
| 2360542e89 | |||
| bdb7d25ac1 | |||
| f0e1078c71 | |||
| 7bfdb01207 | |||
| a80ba6260e | |||
| b90799c0e9 | |||
| 873078028b |
@@ -327,8 +327,8 @@ jobs:
|
||||
uses: ./.github/workflows/build-macos.yml
|
||||
with:
|
||||
platform: macos-x64
|
||||
runs-on: 'macos-13'
|
||||
xcode-toolset-version: '14.3.1'
|
||||
runs-on: 'macos-15-intel'
|
||||
xcode-toolset-version: '16.4'
|
||||
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-14'
|
||||
xcode-toolset-version: '15.4'
|
||||
runs-on: 'macos-15'
|
||||
xcode-toolset-version: '16.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-14
|
||||
runs-on: macos-15
|
||||
dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }}
|
||||
xcode-toolset-version: '15.4'
|
||||
xcode-toolset-version: '16.4'
|
||||
debug-suffix: -debug
|
||||
|
||||
test-windows-x64:
|
||||
|
||||
+1
-1
@@ -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 1.</p>
|
||||
performance. Defaults to 4.</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
@@ -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 1.
|
||||
adjust this factor to compensate for less performance. Defaults to 4.
|
||||
|
||||
#### FAILURE_HANDLER_TIMEOUT
|
||||
|
||||
|
||||
+2
-2
@@ -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. It was not easy changing it to a `1`.
|
||||
JTREG_AUTO_TIMEOUT_FACTOR := 1
|
||||
# Please reach consensus before changing this.
|
||||
JTREG_AUTO_TIMEOUT_FACTOR := 4
|
||||
|
||||
ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), )
|
||||
JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt
|
||||
|
||||
@@ -116,6 +116,9 @@ 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
|
||||
|
||||
@@ -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"`
|
||||
check_date=`$DATE --version 2>&1 | $GREP "GNU\|BusyBox\|uutils"`
|
||||
if test "x$check_date" != x; then
|
||||
AC_MSG_RESULT([yes])
|
||||
IS_GNU_DATE=yes
|
||||
|
||||
@@ -408,27 +408,6 @@ 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
|
||||
])
|
||||
|
||||
@@ -444,13 +423,8 @@ 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])
|
||||
|
||||
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
|
||||
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])
|
||||
|
||||
# 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,7 +44,3 @@ 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))
|
||||
|
||||
@@ -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,-bdatapsize:64k -Wl,-btextpsize:64k -Wl,-bstackpsize:64k"
|
||||
-Wl,-bernotok -Wl,-bcdtors:mbr::s -Wl,-bdatapsize:64k -Wl,-btextpsize:64k -Wl,-bstackpsize:64k"
|
||||
BASIC_LDFLAGS_JVM_ONLY="$BASIC_LDFLAGS_JVM_ONLY -Wl,-lC_r -Wl,-bbigtoc"
|
||||
fi
|
||||
|
||||
|
||||
@@ -565,9 +565,14 @@ 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 -fno-sanitize=function,vptr -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
|
||||
UBSAN_LDFLAGS="$UBSAN_LDFLAGS -fno-sanitize=function,vptr -Wl,-bbigtoc"
|
||||
UBSAN_CFLAGS="$UBSAN_CFLAGS -DLLVM_SYMBOLIZER=$(dirname $(dirname $CC))/tools/ibm-llvm-symbolizer"
|
||||
UBSAN_LDFLAGS="$UBSAN_LDFLAGS -Wl,-bbigtoc"
|
||||
LD="$LDCXX"
|
||||
fi
|
||||
UTIL_ARG_ENABLE(NAME: ubsan, DEFAULT: false, RESULT: UBSAN_ENABLED,
|
||||
DESC: [enable UndefinedBehaviorSanitizer],
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
################################################################################
|
||||
|
||||
# Minimum supported versions
|
||||
JTREG_MINIMUM_VERSION=8
|
||||
JTREG_MINIMUM_VERSION=8.1
|
||||
GTEST_MINIMUM_VERSION=1.14.0
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -136,12 +136,8 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
BASIC_JVM_LIBS="$BASIC_JVM_LIBS $LIBPTHREAD"
|
||||
fi
|
||||
|
||||
# librt for legacy clock_gettime
|
||||
# librt - for timers (timer_* functions)
|
||||
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
|
||||
|
||||
|
||||
@@ -26,24 +26,24 @@
|
||||
# Versions and download locations for dependencies used by GitHub Actions (GHA)
|
||||
|
||||
GTEST_VERSION=1.14.0
|
||||
JTREG_VERSION=8+2
|
||||
JTREG_VERSION=8.1+1
|
||||
|
||||
LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
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
|
||||
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
|
||||
|
||||
ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz
|
||||
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
|
||||
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
|
||||
|
||||
MACOS_AARCH64_BOOT_JDK_EXT=tar.gz
|
||||
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_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_X64_BOOT_JDK_EXT=tar.gz
|
||||
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
|
||||
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
|
||||
|
||||
WINDOWS_X64_BOOT_JDK_EXT=zip
|
||||
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
|
||||
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
|
||||
|
||||
@@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) {
|
||||
};
|
||||
};
|
||||
|
||||
common.boot_jdk_version = "24";
|
||||
common.boot_jdk_build_number = "36";
|
||||
common.boot_jdk_version = "25";
|
||||
common.boot_jdk_build_number = "37";
|
||||
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",
|
||||
build_number: "2",
|
||||
file: "bundles/jtreg-8+2.zip",
|
||||
version: "8.1",
|
||||
build_number: "1",
|
||||
file: "bundles/jtreg-8.1+1.zip",
|
||||
environment_name: "JT_HOME",
|
||||
environment_path: input.get("jtreg", "home_path") + "/bin",
|
||||
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
|
||||
|
||||
@@ -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="24 25 26"
|
||||
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26"
|
||||
DEFAULT_JDK_SOURCE_TARGET_VERSION=26
|
||||
DEFAULT_PROMOTED_VERSION_PRE=ea
|
||||
|
||||
@@ -32,11 +32,6 @@
|
||||
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
|
||||
|
||||
@@ -25,13 +25,6 @@
|
||||
# 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
|
||||
@@ -407,8 +400,7 @@ FF 009F
|
||||
425D FF09
|
||||
425E FF1B
|
||||
425F FFE2
|
||||
#4260 FF0D
|
||||
4260 2212
|
||||
4260 FF0D
|
||||
4261 FF0F
|
||||
426A FFE4
|
||||
426B FF0C
|
||||
|
||||
+26
-26
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 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
|
||||
@@ -57,61 +57,61 @@
|
||||
|
||||
COMMA := ,
|
||||
|
||||
os := $(shell uname -o)
|
||||
cpu := $(shell uname -p)
|
||||
OS := $(shell uname -o)
|
||||
CPU := $(shell uname -m)
|
||||
|
||||
# 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 $(configs) $(host_platforms) clean dist-clean
|
||||
.PHONY : all compile tars $(HOST_PLATFORMS) clean dist-clean
|
||||
|
||||
+109
-78
@@ -39,7 +39,7 @@
|
||||
# Fix this...
|
||||
#
|
||||
|
||||
uppercase = $(shell echo $1 | tr a-z A-Z)
|
||||
lowercase = $(shell echo $1 | tr A-Z a-z)
|
||||
|
||||
$(info TARGET=$(TARGET))
|
||||
$(info HOST=$(HOST))
|
||||
@@ -104,26 +104,48 @@ endif
|
||||
################################################################################
|
||||
# Define external dependencies
|
||||
|
||||
gcc_ver_only := 14.2.0
|
||||
binutils_ver_only := 2.43
|
||||
ccache_ver_only := 4.10.2
|
||||
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
|
||||
CCACHE_CMAKE_BASED := 1
|
||||
mpfr_ver_only := 4.2.1
|
||||
gmp_ver_only := 6.3.0
|
||||
mpc_ver_only := 1.3.1
|
||||
gdb_ver_only := 15.2
|
||||
CCACHE_SHA512 := 3815c71d7266c32839acb306763268018acc58b3bbbd9ec79fc101e4217c1720d2ad2f01645bf69168c1c61d27700b6f3bb755cfa82689cca69824f015653f3c
|
||||
|
||||
dependencies := gcc binutils ccache mpfr gmp mpc gdb
|
||||
GCC_VER_ONLY := 14.2.0
|
||||
GCC_BASE_URL := $(GNU_BASE_URL)/gcc
|
||||
GCC_SHA512 := 932bdef0cda94bacedf452ab17f103c0cb511ff2cec55e9112fc0328cbf1d803b42595728ea7b200e0a057c03e85626f937012e49a7515bc5dd256b2bf4bc396
|
||||
|
||||
$(foreach dep,$(dependencies),$(eval $(dep)_ver := $(dep)-$($(dep)_ver_only)))
|
||||
GDB_VER_ONLY := 15.2
|
||||
GDB_BASE_URL := $(GNU_BASE_URL)/gdb
|
||||
GDB_SHA512 := 624007deceb5b15ba89c0725883d1a699fa46714ef30887f3d0165e17c5d65d634671740a135aa69e437d916218abb08cfa2a38ed309ff19d48f51da56b2a8ba
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
REQUIRED_MIN_MAKE_MAJOR_VERSION := 4
|
||||
ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),)
|
||||
@@ -180,10 +202,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
|
||||
@@ -198,10 +220,10 @@ download-rpms:
|
||||
################################################################################
|
||||
# Unpack source packages
|
||||
|
||||
# Generate downloading + unpacking of sources.
|
||||
define Download
|
||||
# Generate downloading + checksum verification of sources.
|
||||
define DownloadVerify
|
||||
# Allow override
|
||||
$(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)))))
|
||||
$(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)_URL))))
|
||||
$(1)_DIR = $(abspath $(SRCDIR)/$$($(1)_DIRNAME))
|
||||
ifeq ($$($(1)_CMAKE_BASED),)
|
||||
$(1)_CFG = $$($(1)_DIR)/configure
|
||||
@@ -212,7 +234,7 @@ define Download
|
||||
$(1)_SRC_MARKER = $$($(1)_DIR)/CMakeLists.txt
|
||||
$(1)_CONFIG = $$(CMAKE_CONFIG) $$($(1)_DIR)
|
||||
endif
|
||||
$(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)))
|
||||
$(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)_URL))
|
||||
|
||||
$$($(1)_SRC_MARKER) : $$($(1)_FILE)
|
||||
mkdir -p $$(SRCDIR)
|
||||
@@ -224,11 +246,20 @@ define Download
|
||||
touch $$@
|
||||
|
||||
$$($(1)_FILE) :
|
||||
wget -P $(DOWNLOAD) $$($(1))
|
||||
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 $$@
|
||||
endef
|
||||
|
||||
# Download and unpack all source packages
|
||||
$(foreach dep,$(dependencies),$(eval $(call Download,$(call uppercase,$(dep)))))
|
||||
$(foreach dep,$(DEPENDENCIES),$(eval $(call DownloadVerify,$(dep))))
|
||||
|
||||
################################################################################
|
||||
# Unpack RPMS
|
||||
@@ -250,7 +281,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 :
|
||||
@@ -277,7 +308,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' \
|
||||
@@ -293,10 +324,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
|
||||
@@ -305,7 +336,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))
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -345,48 +376,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
|
||||
@@ -397,8 +428,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)
|
||||
@@ -417,7 +448,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)
|
||||
@@ -432,7 +463,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)
|
||||
@@ -449,7 +480,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)
|
||||
@@ -468,11 +499,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)), )
|
||||
@@ -487,7 +518,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)
|
||||
@@ -509,17 +540,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)
|
||||
( \
|
||||
@@ -532,9 +563,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:" > $@
|
||||
@@ -543,7 +574,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)
|
||||
@@ -554,12 +585,12 @@ $(BUILDDIR)/$(ccache_ver)/Makefile \
|
||||
) > $(@D)/log.config 2>&1
|
||||
@echo 'done'
|
||||
|
||||
gccpatch = $(TARGETDIR)/gcc-patched
|
||||
GCC_PATCHED = $(TARGETDIR)/gcc-patched
|
||||
|
||||
################################################################################
|
||||
# For some reason cpp is not created as a target-compiler
|
||||
ifeq ($(HOST),$(TARGET))
|
||||
$(gccpatch) : $(gcc) link_libs
|
||||
$(GCC_PATCHED) : $(GCC) link_libs
|
||||
@echo -n 'Creating compiler symlinks...'
|
||||
@for f in cpp; do \
|
||||
if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ]; \
|
||||
@@ -587,7 +618,7 @@ ifeq ($(HOST),$(TARGET))
|
||||
done;)
|
||||
@echo 'done'
|
||||
else
|
||||
$(gccpatch) :
|
||||
$(GCC_PATCHED) :
|
||||
@echo 'done'
|
||||
endif
|
||||
|
||||
@@ -615,7 +646,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"' >> $@
|
||||
@@ -651,32 +682,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) $(gccpatch)
|
||||
gdb : $(gdb)
|
||||
all : binutils gcc bfdlib $(PREFIX)/devkit.info $(missing-links) $(SYSROOT_LINKS) \
|
||||
gcc : sysroot $(GCC) $(GCC_PATCHED)
|
||||
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
|
||||
|
||||
@@ -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 http://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm
|
||||
wget https://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
|
||||
|
||||
@@ -189,7 +189,6 @@ $(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,6 +22,7 @@
|
||||
// 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": {
|
||||
|
||||
@@ -27,7 +27,5 @@
|
||||
|
||||
DOCLINT += -Xdoclint:all/protected \
|
||||
'-Xdoclint/package:java.*,javax.*'
|
||||
COPY += .js
|
||||
CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#
|
||||
# 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, \
|
||||
))
|
||||
|
||||
################################################################################
|
||||
@@ -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,10 +2568,6 @@ 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);
|
||||
|
||||
@@ -7081,29 +7081,31 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{
|
||||
%}
|
||||
|
||||
instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2,
|
||||
vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{
|
||||
vReg tmp3, 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 tmp4, TEMP ptmp, TEMP pgtmp);
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp);
|
||||
match(Set dst (CompressV src pg));
|
||||
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %}
|
||||
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $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,$tmp4$$FloatRegister,
|
||||
$ptmp$$PRegister, $pgtmp$$PRegister);
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister,
|
||||
$ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes);
|
||||
%}
|
||||
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);
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister,
|
||||
length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@@ -5069,29 +5069,31 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{
|
||||
%}
|
||||
|
||||
instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2,
|
||||
vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{
|
||||
vReg tmp3, 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 tmp4, TEMP ptmp, TEMP pgtmp);
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp);
|
||||
match(Set dst (CompressV src pg));
|
||||
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %}
|
||||
format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $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,$tmp4$$FloatRegister,
|
||||
$ptmp$$PRegister, $pgtmp$$PRegister);
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister,
|
||||
$ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes);
|
||||
%}
|
||||
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);
|
||||
$tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister,
|
||||
length_in_bytes);
|
||||
%}
|
||||
ins_pipe(pipe_slow);
|
||||
%}
|
||||
|
||||
@@ -3486,6 +3486,7 @@ 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
|
||||
|
||||
@@ -383,13 +383,6 @@ 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,114 +2203,117 @@ 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: src, mask
|
||||
// Preserves: mask, vzr
|
||||
void C2_MacroAssembler::sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask,
|
||||
FloatRegister vtmp1, FloatRegister vtmp2,
|
||||
PRegister pgtmp) {
|
||||
FloatRegister vzr, FloatRegister vtmp,
|
||||
PRegister pgtmp, unsigned vector_length_in_bytes) {
|
||||
assert(pgtmp->is_governing(), "This register has to be a governing predicate register");
|
||||
assert_different_registers(dst, src, vtmp1, vtmp2);
|
||||
// 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(mask, pgtmp);
|
||||
|
||||
// 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);
|
||||
// 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
|
||||
|
||||
// Extend lowest half to type INT.
|
||||
// dst = 00004444 00003333 00002222 00001111
|
||||
// dst = 00dd 00cc 00bb 00aa
|
||||
sve_uunpklo(dst, S, src);
|
||||
// pgtmp = 00000001 00000000 00000001 00000001
|
||||
// pgtmp = 0001 0000 0001 0001
|
||||
sve_punpklo(pgtmp, mask);
|
||||
// Pack the active elements in size of type INT to the right,
|
||||
// and fill the remainings with zero.
|
||||
// dst = 00000000 00004444 00002222 00001111
|
||||
// dst = 0000 00dd 00bb 00aa
|
||||
sve_compact(dst, S, dst, pgtmp);
|
||||
// Narrow the result back to type SHORT.
|
||||
// dst = 0000 0000 0000 0000 0000 4444 2222 1111
|
||||
sve_uzp1(dst, H, dst, vtmp2);
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Count the active elements of lowest half.
|
||||
// rscratch1 = 3
|
||||
sve_cntp(rscratch1, S, ptrue, pgtmp);
|
||||
|
||||
// Repeat to the highest half.
|
||||
// pgtmp = 00000001 00000000 00000000 00000001
|
||||
// pgtmp = 0001 0000 0000 0001
|
||||
sve_punpkhi(pgtmp, mask);
|
||||
// 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);
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Clobbers: rscratch1, rscratch2
|
||||
// Preserves: src, mask
|
||||
void C2_MacroAssembler::sve_compress_byte(FloatRegister dst, FloatRegister src, PRegister mask,
|
||||
FloatRegister vtmp1, FloatRegister vtmp2,
|
||||
FloatRegister vtmp3, FloatRegister vtmp4,
|
||||
PRegister ptmp, PRegister pgtmp) {
|
||||
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3,
|
||||
PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes) {
|
||||
assert(pgtmp->is_governing(), "This register has to be a governing predicate register");
|
||||
assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3, vtmp4);
|
||||
assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3);
|
||||
assert_different_registers(mask, ptmp, pgtmp);
|
||||
// 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
|
||||
// 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);
|
||||
|
||||
sve_dup(vtmp4, B, 0);
|
||||
// Extend lowest half to type SHORT.
|
||||
// vtmp1 = 0044 0033 0022 0011
|
||||
// vtmp1 = 0h 0g 0f 0e 0d 0c 0b 0a
|
||||
sve_uunpklo(vtmp1, H, src);
|
||||
// ptmp = 0001 0000 0001 0001
|
||||
// ptmp = 00 01 00 00 00 01 00 01
|
||||
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 = 0001 0000 0000 0001
|
||||
// ptmp = 00 01 00 00 00 00 00 01
|
||||
sve_punpkhi(ptmp, mask);
|
||||
// vtmp1 = 0088 0077 0066 0055
|
||||
// vtmp2 = 0q 0p 0n 0m 0l 0k 0j 0i
|
||||
sve_uunpkhi(vtmp2, H, src);
|
||||
// vtmp1 = 0000 0000 0088 0055
|
||||
sve_compress_short(vtmp1, vtmp2, ptmp, vtmp3, vtmp4, pgtmp);
|
||||
// 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);
|
||||
|
||||
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);
|
||||
// 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);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ) {
|
||||
|
||||
@@ -173,13 +173,12 @@
|
||||
// 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, FloatRegister vtmp4,
|
||||
PRegister ptmp, PRegister pgtmp);
|
||||
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3,
|
||||
PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes);
|
||||
|
||||
void sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask,
|
||||
FloatRegister vtmp1, FloatRegister vtmp2,
|
||||
PRegister pgtmp);
|
||||
FloatRegister vzr, FloatRegister vtmp,
|
||||
PRegister pgtmp, unsigned vector_length_in_bytes);
|
||||
|
||||
void neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ);
|
||||
|
||||
|
||||
@@ -228,8 +228,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
nmethod* nm = sender_blob->as_nmethod_or_null();
|
||||
if (nm != nullptr) {
|
||||
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
|
||||
nm->method()->is_method_handle_intrinsic()) {
|
||||
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -454,48 +453,6 @@ 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 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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.
|
||||
*
|
||||
@@ -141,8 +141,6 @@
|
||||
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.
|
||||
@@ -152,11 +150,6 @@
|
||||
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,8 +116,6 @@ 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;
|
||||
@@ -223,7 +221,6 @@ 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,8 +35,6 @@ 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,3 +1704,14 @@ 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,6 +319,8 @@ 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,24 +39,22 @@ 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) {
|
||||
// In order to make sure the transition state is valid for "this"
|
||||
// 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.
|
||||
|
||||
// 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,12 +634,13 @@ 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,
|
||||
@@ -5630,38 +5631,6 @@ 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,9 +983,6 @@ 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,7 +90,6 @@ 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,11 +985,8 @@ 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
|
||||
@@ -1005,50 +1002,6 @@ 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,6 +168,7 @@ 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;
|
||||
|
||||
@@ -231,9 +232,12 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
|
||||
__ stop("patching the wrong bytecode");
|
||||
__ bind(L_okay);
|
||||
#endif
|
||||
|
||||
// patch bytecode
|
||||
__ strb(bc_reg, at_bcp(0));
|
||||
// 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);
|
||||
__ bind(L_patch_done);
|
||||
}
|
||||
|
||||
@@ -2269,7 +2273,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 resolved, clinit_barrier_slow;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
__ load_method_entry(Rcache, index);
|
||||
@@ -2284,11 +2288,20 @@ 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?
|
||||
__ br(Assembler::EQ, resolved);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -2297,14 +2310,7 @@ 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(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);
|
||||
}
|
||||
__ bind(L_done);
|
||||
}
|
||||
|
||||
void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
@@ -2313,7 +2319,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
const Register temp = r19;
|
||||
assert_different_registers(Rcache, index, temp);
|
||||
|
||||
Label resolved;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
@@ -2332,16 +2338,29 @@ 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?
|
||||
__ br(Assembler::EQ, resolved);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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(resolved);
|
||||
__ bind(L_done);
|
||||
}
|
||||
|
||||
void TemplateTable::load_resolved_field_entry(Register obj,
|
||||
@@ -3079,6 +3098,7 @@ 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;
|
||||
@@ -3168,6 +3188,8 @@ 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
|
||||
@@ -3234,7 +3256,9 @@ 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,6 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -222,10 +223,13 @@ 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(0xd40) || model_is(0xd4f) ||
|
||||
model_is(0xd8e) || model_is(0xd84))) {
|
||||
if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
|
||||
FLAG_SET_DEFAULT(UseSIMDForMemoryOps, true);
|
||||
}
|
||||
@@ -260,7 +264,9 @@ void VM_Version::initialize() {
|
||||
// Neoverse
|
||||
// V1: 0xd40
|
||||
// V2: 0xd4f
|
||||
if (_cpu == CPU_ARM && (model_is(0xd40) || model_is(0xd4f))) {
|
||||
// V3: 0xd84
|
||||
if (_cpu == CPU_ARM &&
|
||||
(model_is(0xd40) || model_is(0xd4f) || model_is(0xd84))) {
|
||||
if (FLAG_IS_DEFAULT(UseCryptoPmullForCRC32)) {
|
||||
FLAG_SET_DEFAULT(UseCryptoPmullForCRC32, true);
|
||||
}
|
||||
|
||||
@@ -199,6 +199,8 @@ 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; }
|
||||
|
||||
@@ -1154,10 +1154,6 @@ 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());
|
||||
}
|
||||
@@ -1248,23 +1244,6 @@ 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");
|
||||
@@ -8799,7 +8778,6 @@ 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);
|
||||
@@ -8808,20 +8786,6 @@ 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);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2008, 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
|
||||
@@ -432,8 +432,7 @@ 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) + (_method_handle_invoke ? 1 : 0)) *
|
||||
NativeInstruction::instruction_size;
|
||||
return (far ? 3 : 1) * NativeInstruction::instruction_size;
|
||||
}
|
||||
|
||||
int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
|
||||
@@ -174,11 +174,6 @@ 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;
|
||||
|
||||
@@ -275,14 +275,6 @@ 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");
|
||||
|
||||
@@ -339,7 +331,6 @@ 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();
|
||||
@@ -372,9 +363,6 @@ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -329,56 +329,6 @@ 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) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -85,20 +85,11 @@
|
||||
// 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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -112,8 +112,6 @@ 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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -364,7 +364,6 @@ 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
|
||||
|
||||
@@ -264,11 +264,6 @@ 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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -0,0 +1,649 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -374,15 +374,6 @@ 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,14 +193,19 @@ 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);
|
||||
|
||||
// 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);
|
||||
if (TrapBasedNMethodEntryBarriers) {
|
||||
__ tw(Assembler::traptoLessThanUnsigned | Assembler::traptoGreaterThanUnsigned, R0, tmp);
|
||||
} else {
|
||||
__ cmpw(CR0, R0, tmp);
|
||||
|
||||
__ bnectrl(CR0);
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Oops may have been changed. Make those updates observable.
|
||||
// "isync" can serve both, data and instruction patching.
|
||||
|
||||
@@ -100,17 +100,21 @@ public:
|
||||
|
||||
verify_op_code(current_instruction, Assembler::LD_OPCODE);
|
||||
|
||||
// cmpw (mnemonic)
|
||||
verify_op_code(current_instruction, Assembler::CMP_OPCODE);
|
||||
if (TrapBasedNMethodEntryBarriers) {
|
||||
verify_op_code(current_instruction, Assembler::TW_OPCODE);
|
||||
} else {
|
||||
// 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
|
||||
}
|
||||
@@ -131,9 +135,10 @@ 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() + (-8 * 4);
|
||||
address barrier_address = nm->code_begin() + nm->frame_complete_offset() -
|
||||
(TrapBasedNMethodEntryBarriers ? 4 : 8) * BytesPerInstWord;
|
||||
if (bs_asm->nmethod_patching_type() != NMethodPatchingType::stw_instruction_and_data_patch) {
|
||||
barrier_address -= 4; // isync (see nmethod_entry_barrier)
|
||||
barrier_address -= BytesPerInstWord; // isync (see nmethod_entry_barrier)
|
||||
}
|
||||
|
||||
auto barrier = reinterpret_cast<NativeNMethodBarrier*>(barrier_address);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, 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,8 +43,6 @@ 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
|
||||
|
||||
|
||||
@@ -145,6 +145,8 @@ 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.") \
|
||||
|
||||
@@ -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,11 +56,9 @@ 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;
|
||||
}
|
||||
|
||||
@@ -75,6 +73,6 @@ public:
|
||||
|
||||
intptr_t* last_Java_fp() const { return *(intptr_t**)_last_Java_sp; }
|
||||
|
||||
void set_last_Java_sp(intptr_t* sp) { OrderAccess::release(); _last_Java_sp = sp; }
|
||||
void set_last_Java_sp(intptr_t* sp) { _last_Java_sp = sp; }
|
||||
|
||||
#endif // CPU_PPC_JAVAFRAMEANCHOR_PPC_HPP
|
||||
|
||||
@@ -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), "already patched");
|
||||
assert(!decode(i1, i2) || NMethodRelocation, "already patched");
|
||||
|
||||
cb_offset = cb_offset >> 2;
|
||||
if (((oopmap_slot & ppc_oopmap_slot_mask) != oopmap_slot) || ((cb_offset & ppc_cb_offset_mask) != cb_offset)) {
|
||||
|
||||
@@ -77,6 +77,12 @@ 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) {
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -2473,10 +2473,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
//----------ENCODING BLOCK-----------------------------------------------------
|
||||
@@ -3434,7 +3430,6 @@ 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;
|
||||
|
||||
@@ -1639,7 +1639,6 @@ 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
|
||||
@@ -1655,12 +1654,9 @@ 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"));
|
||||
}
|
||||
|
||||
@@ -1681,7 +1677,6 @@ 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 {");
|
||||
@@ -1692,57 +1687,8 @@ 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);
|
||||
|
||||
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);
|
||||
__ ld_ptr(tmp2, ContinuationEntry::parent_offset(), R1_SP);
|
||||
__ st_ptr(tmp2, JavaThread::cont_entry_offset(), R16_thread);
|
||||
DEBUG_ONLY(__ block_comment("} clean"));
|
||||
}
|
||||
|
||||
|
||||
@@ -2179,17 +2179,11 @@ 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 Lresolved, Ldone, L_clinit_barrier_slow;
|
||||
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
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);
|
||||
@@ -2197,20 +2191,8 @@ 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);
|
||||
__ beq(CR0, Lresolved);
|
||||
__ bne(CR0, 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, 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
|
||||
@@ -2220,18 +2202,26 @@ 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, nullptr /*L_fast_path*/, &L_clinit_barrier_slow);
|
||||
__ clinit_barrier(klass, R16_thread, &L_done, /*L_slow_path*/ nullptr);
|
||||
} else {
|
||||
__ b(L_done);
|
||||
}
|
||||
|
||||
__ bind(Ldone);
|
||||
// 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);
|
||||
}
|
||||
|
||||
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 resolved;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
@@ -2246,19 +2236,34 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
: in_bytes(ResolvedFieldEntry::put_code_offset());
|
||||
__ lbz(R0, code_offset, Rcache);
|
||||
__ cmpwi(CR0, R0, (int)code); // have we resolved this bytecode?
|
||||
__ beq(CR0, resolved);
|
||||
__ 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);
|
||||
}
|
||||
|
||||
// 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, (int)code);
|
||||
__ li(R4_ARG2, code);
|
||||
__ call_VM(noreg, entry, R4_ARG2);
|
||||
|
||||
// Update registers with resolved info
|
||||
__ load_field_entry(Rcache, index);
|
||||
__ bind(resolved);
|
||||
|
||||
// Use acquire semantics for the bytecode (see ResolvedFieldEntry::fill_in()).
|
||||
__ isync(); // Order load wrt. succeeding loads.
|
||||
__ bind(L_done);
|
||||
}
|
||||
|
||||
void TemplateTable::load_resolved_field_entry(Register obj,
|
||||
|
||||
@@ -87,8 +87,10 @@ void VM_Version::initialize() {
|
||||
if (!UseSIGTRAP) {
|
||||
MSG(TrapBasedICMissChecks);
|
||||
MSG(TrapBasedNullChecks);
|
||||
FLAG_SET_ERGO(TrapBasedNullChecks, false);
|
||||
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
|
||||
MSG(TrapBasedNMethodEntryBarriers);
|
||||
FLAG_SET_ERGO(TrapBasedNullChecks, false);
|
||||
FLAG_SET_ERGO(TrapBasedICMissChecks, false);
|
||||
FLAG_SET_ERGO(TrapBasedNMethodEntryBarriers, false);
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
@@ -97,6 +99,10 @@ 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)) {
|
||||
|
||||
@@ -64,6 +64,7 @@ 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; }
|
||||
|
||||
|
||||
@@ -914,6 +914,17 @@ 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;
|
||||
@@ -3693,19 +3704,15 @@ public:
|
||||
// --------------------------
|
||||
// Upper Immediate Instruction
|
||||
// --------------------------
|
||||
#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); \
|
||||
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);
|
||||
}
|
||||
|
||||
INSN(lui);
|
||||
|
||||
#undef INSN
|
||||
|
||||
// Cache Management Operations
|
||||
// These instruction may be turned off for user space.
|
||||
|
||||
@@ -377,11 +377,6 @@ 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,6 +1350,7 @@ 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");
|
||||
@@ -1360,6 +1361,7 @@ 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");
|
||||
@@ -1842,6 +1844,10 @@ 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) {
|
||||
|
||||
@@ -1687,6 +1687,7 @@ 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);
|
||||
@@ -1759,29 +1760,143 @@ 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();
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,11 +92,15 @@
|
||||
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);
|
||||
|
||||
|
||||
@@ -217,8 +217,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
nmethod* nm = sender_blob->as_nmethod_or_null();
|
||||
if (nm != nullptr) {
|
||||
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
|
||||
nm->method()->is_method_handle_intrinsic()) {
|
||||
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -427,49 +426,6 @@ 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 {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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,17 +179,10 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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,8 +114,6 @@ 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;
|
||||
@@ -215,7 +213,6 @@ 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, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2025, 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,8 +44,6 @@ 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,6 +1841,15 @@ 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,6 +300,8 @@ 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,25 +39,23 @@ 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) {
|
||||
// In order to make sure the transition state is valid for "this"
|
||||
// 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.
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -225,36 +225,6 @@ 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();
|
||||
@@ -355,14 +325,15 @@ 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
|
||||
@@ -389,12 +360,14 @@ 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,
|
||||
@@ -5013,7 +4986,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);
|
||||
IncompressibleScope scope(this); // relocations
|
||||
assert(!in_compressible_scope(), "Must be");
|
||||
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, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, 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,9 +849,6 @@ 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();
|
||||
|
||||
|
||||
@@ -331,13 +331,10 @@ 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() {
|
||||
return uint_at(0) == 0xc0101073; // an illegal instruction, 'csrrw x0, time, x0'
|
||||
// an illegal instruction, 'csrrw x0, time, x0'
|
||||
uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::time, x0);
|
||||
return uint_at(0) == encoded;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
@@ -347,6 +344,8 @@ 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
|
||||
@@ -378,6 +377,7 @@ 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,14 +389,17 @@ bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) {
|
||||
return true; // successfully encoded
|
||||
}
|
||||
|
||||
void NativeDeoptInstruction::verify() {
|
||||
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;
|
||||
}
|
||||
|
||||
// Inserts an undefined instruction at a given pc
|
||||
void NativeDeoptInstruction::insert(address code_pos) {
|
||||
// 0xc0201073 encodes CSRRW x0, instret, x0
|
||||
uint32_t insn = 0xc0201073;
|
||||
uint32_t *pos = (uint32_t *) code_pos;
|
||||
*pos = insn;
|
||||
MacroAssembler::assert_alignment(code_pos);
|
||||
uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0);
|
||||
Assembler::sd_instr(code_pos, encoded);
|
||||
ICache::invalidate_range(code_pos, 4);
|
||||
}
|
||||
|
||||
@@ -294,12 +294,6 @@ 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;
|
||||
@@ -353,14 +347,7 @@ class NativeDeoptInstruction: public NativeInstruction {
|
||||
address instruction_address() const { return addr_at(instruction_offset); }
|
||||
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||
|
||||
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;
|
||||
}
|
||||
static bool is_deopt_at(address instr);
|
||||
|
||||
// MT-safe patching
|
||||
static void insert(address code_pos);
|
||||
|
||||
@@ -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,6 +1269,26 @@ 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
|
||||
@@ -1306,7 +1326,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
|
||||
@@ -2084,10 +2104,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
|
||||
@@ -2102,7 +2122,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) {
|
||||
@@ -2132,10 +2152,6 @@ 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++) {
|
||||
@@ -8175,7 +8191,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");
|
||||
@@ -10509,6 +10525,7 @@ instruct CallRuntimeDirect(method meth)
|
||||
ins_encode(riscv_enc_java_to_runtime(meth));
|
||||
|
||||
ins_pipe(pipe_class_call);
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Runtime Instruction
|
||||
@@ -10526,6 +10543,7 @@ 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
|
||||
@@ -10543,6 +10561,7 @@ instruct CallLeafDirectVector(method meth)
|
||||
ins_encode(riscv_enc_java_to_runtime(meth));
|
||||
|
||||
ins_pipe(pipe_class_call);
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// Call Runtime Instruction
|
||||
@@ -10560,6 +10579,7 @@ instruct CallLeafNoFPDirect(method meth)
|
||||
ins_encode(riscv_enc_java_to_runtime(meth));
|
||||
|
||||
ins_pipe(pipe_class_call);
|
||||
ins_alignment(4);
|
||||
%}
|
||||
|
||||
// ============================================================================
|
||||
@@ -10971,6 +10991,7 @@ 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);
|
||||
|
||||
@@ -4080,6 +4080,28 @@ 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,
|
||||
|
||||
@@ -885,11 +885,8 @@ 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
|
||||
@@ -905,50 +902,6 @@ 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() */);
|
||||
@@ -1002,20 +955,23 @@ static void gen_continuation_enter(MacroAssembler* masm,
|
||||
|
||||
__ bnez(c_rarg2, call_thaw);
|
||||
|
||||
// Make sure the call is patchable
|
||||
__ align(NativeInstruction::instruction_size);
|
||||
address call_pc;
|
||||
{
|
||||
Assembler::IncompressibleScope scope(masm);
|
||||
// Make sure the call is patchable
|
||||
__ align(NativeInstruction::instruction_size);
|
||||
|
||||
const address tr_call = __ reloc_call(resolve);
|
||||
if (tr_call == nullptr) {
|
||||
fatal("CodeCache is full at gen_continuation_enter");
|
||||
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();
|
||||
}
|
||||
|
||||
oop_maps->add_gc_map(__ pc() - start, map);
|
||||
__ post_call_nop();
|
||||
|
||||
__ j(exit);
|
||||
|
||||
address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call);
|
||||
address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc);
|
||||
if (stub == nullptr) {
|
||||
fatal("CodeCache is full at gen_continuation_enter");
|
||||
}
|
||||
@@ -1034,26 +990,36 @@ static void gen_continuation_enter(MacroAssembler* masm,
|
||||
|
||||
__ bnez(c_rarg2, call_thaw);
|
||||
|
||||
// Make sure the call is patchable
|
||||
__ align(NativeInstruction::instruction_size);
|
||||
address call_pc;
|
||||
{
|
||||
Assembler::IncompressibleScope scope(masm);
|
||||
// Make sure the call is patchable
|
||||
__ align(NativeInstruction::instruction_size);
|
||||
|
||||
const address tr_call = __ reloc_call(resolve);
|
||||
if (tr_call == nullptr) {
|
||||
fatal("CodeCache is full at gen_continuation_enter");
|
||||
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();
|
||||
}
|
||||
|
||||
oop_maps->add_gc_map(__ pc() - start, map);
|
||||
__ post_call_nop();
|
||||
|
||||
__ j(exit);
|
||||
|
||||
__ bind(call_thaw);
|
||||
|
||||
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();
|
||||
// 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();
|
||||
}
|
||||
|
||||
__ bind(exit);
|
||||
ContinuationEntry::_cleanup_offset = __ pc() - start;
|
||||
@@ -1082,7 +1048,7 @@ static void gen_continuation_enter(MacroAssembler* masm,
|
||||
__ jr(x11); // the exception handler
|
||||
}
|
||||
|
||||
address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call);
|
||||
address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc);
|
||||
if (stub == nullptr) {
|
||||
fatal("CodeCache is full at gen_continuation_enter");
|
||||
}
|
||||
@@ -1115,10 +1081,16 @@ 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();
|
||||
|
||||
__ 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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
__ mv(c_rarg0, xthread);
|
||||
__ set_last_Java_frame(sp, fp, the_pc, t0);
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
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,6 +6624,24 @@ 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
|
||||
|
||||
/**
|
||||
@@ -6818,6 +6836,10 @@ 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);
|
||||
|
||||
@@ -133,6 +133,7 @@ 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;
|
||||
|
||||
@@ -196,7 +197,11 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
|
||||
__ bind(L_okay);
|
||||
#endif
|
||||
|
||||
// patch bytecode
|
||||
// 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);
|
||||
__ sb(bc_reg, at_bcp(0));
|
||||
__ bind(L_patch_done);
|
||||
}
|
||||
@@ -2168,7 +2173,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 resolved, clinit_barrier_slow;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
__ load_method_entry(Rcache, index);
|
||||
@@ -2185,12 +2190,20 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
|
||||
__ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore);
|
||||
|
||||
__ mv(t0, (int) code);
|
||||
__ beq(temp, t0, resolved); // have we resolved this bytecode?
|
||||
|
||||
// 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?
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -2199,14 +2212,7 @@ 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(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);
|
||||
}
|
||||
__ bind(L_done);
|
||||
}
|
||||
|
||||
void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
@@ -2215,13 +2221,13 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
const Register temp = x9;
|
||||
assert_different_registers(Rcache, index, temp);
|
||||
|
||||
Label resolved;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
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");
|
||||
@@ -2235,16 +2241,29 @@ 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?
|
||||
__ beq(temp, t0, resolved);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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(resolved);
|
||||
__ bind(L_done);
|
||||
}
|
||||
|
||||
void TemplateTable::load_resolved_field_entry(Register obj,
|
||||
@@ -3014,6 +3033,7 @@ 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;
|
||||
@@ -3101,6 +3121,8 @@ 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
|
||||
@@ -3156,7 +3178,9 @@ 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)
|
||||
|
||||
@@ -24,9 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#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"
|
||||
@@ -34,21 +39,72 @@
|
||||
#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 };
|
||||
|
||||
#define DEF_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
|
||||
VM_Version::NAME##RVExtFeatureValue VM_Version::NAME;
|
||||
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;
|
||||
RV_EXT_FEATURE_FLAGS(DEF_RV_EXT_FEATURE)
|
||||
#undef DEF_RV_EXT_FEATURE
|
||||
|
||||
#define DEF_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
|
||||
VM_Version::NAME##RVNonExtFeatureValue VM_Version::NAME;
|
||||
#define DEF_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
|
||||
VM_Version::PRETTY##RVNonExtFeatureValue VM_Version::PRETTY;
|
||||
RV_NON_EXT_FEATURE_FLAGS(DEF_RV_NON_EXT_FEATURE)
|
||||
#undef DEF_RV_NON_EXT_FEATURE
|
||||
|
||||
#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,
|
||||
#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,
|
||||
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)
|
||||
@@ -103,17 +159,6 @@ 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");
|
||||
@@ -148,7 +193,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);
|
||||
|
||||
@@ -178,9 +223,25 @@ void VM_Version::common_initialize() {
|
||||
(unaligned_scalar.value() == MISALIGNED_SCALAR_FAST));
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(AlignVector) && unaligned_vector.enabled()) {
|
||||
FLAG_SET_DEFAULT(AlignVector,
|
||||
unaligned_vector.value() != MISALIGNED_VECTOR_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __riscv_ztso
|
||||
@@ -199,7 +260,7 @@ void VM_Version::common_initialize() {
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, false);
|
||||
}
|
||||
|
||||
if (UseZicboz && zicboz_block_size.enabled() && zicboz_block_size.value() > 0) {
|
||||
if (UseZicboz && 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);
|
||||
@@ -213,13 +274,8 @@ void VM_Version::common_initialize() {
|
||||
}
|
||||
|
||||
if (UseRVV) {
|
||||
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();
|
||||
}
|
||||
// read vector length from vector CSR vlenb
|
||||
_initial_vector_length = cpu_vector_length();
|
||||
}
|
||||
|
||||
// Misc Intrinsics that could depend on RVV.
|
||||
@@ -239,36 +295,6 @@ 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
|
||||
@@ -527,3 +553,22 @@ 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;
|
||||
}
|
||||
@@ -52,24 +52,19 @@ 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)),
|
||||
_value(-1) {
|
||||
}
|
||||
virtual void enable_feature(int64_t value = 0) {
|
||||
_value = value;
|
||||
}
|
||||
virtual void disable_feature() {
|
||||
_value = -1;
|
||||
_pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)) {
|
||||
}
|
||||
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) \
|
||||
@@ -85,27 +80,35 @@ class VM_Version : public Abstract_VM_Version {
|
||||
} \
|
||||
} \
|
||||
|
||||
#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 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 NO_UPDATE_DEFAULT \
|
||||
void update_flag() {} \
|
||||
@@ -113,88 +116,98 @@ 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 {
|
||||
bool _enabled;
|
||||
static const int64_t DEFAULT_VALUE = -1;
|
||||
int64_t _value;
|
||||
|
||||
public:
|
||||
RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
|
||||
RVFeatureValue(pretty, linux_bit_num, fstring),
|
||||
_enabled(false) {
|
||||
_value(DEFAULT_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;
|
||||
bool enabled() { return _value != DEFAULT_VALUE; }
|
||||
void enable_feature(int64_t value) {
|
||||
assert(value != DEFAULT_VALUE, "Sanity");
|
||||
_value = value;
|
||||
}
|
||||
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
|
||||
@@ -204,47 +217,83 @@ 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) \
|
||||
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)) \
|
||||
/* 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)) \
|
||||
|
||||
#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; \
|
||||
#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; \
|
||||
|
||||
RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE)
|
||||
#undef DECLARE_RV_EXT_FEATURE
|
||||
@@ -252,21 +301,27 @@ class VM_Version : public Abstract_VM_Version {
|
||||
// Non-extension features
|
||||
//
|
||||
#define RV_NON_EXT_FEATURE_FLAGS(decl) \
|
||||
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) \
|
||||
/* 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) \
|
||||
|
||||
#define DECLARE_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
|
||||
struct NAME##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
|
||||
NAME##RVNonExtFeatureValue() : \
|
||||
#define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
|
||||
struct PRETTY##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
|
||||
PRETTY##RVNonExtFeatureValue() : \
|
||||
RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {} \
|
||||
FLAGF; \
|
||||
}; \
|
||||
static NAME##RVNonExtFeatureValue NAME; \
|
||||
static PRETTY##RVNonExtFeatureValue PRETTY; \
|
||||
|
||||
RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE)
|
||||
#undef DECLARE_RV_NON_EXT_FEATURE
|
||||
@@ -276,7 +331,7 @@ private:
|
||||
class RVExtFeatures : public CHeapObj<mtCode> {
|
||||
public:
|
||||
enum RVFeatureIndex {
|
||||
#define DECLARE_RV_FEATURE_ENUM(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##NAME,
|
||||
#define DECLARE_RV_FEATURE_ENUM(PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##ext_##PRETTY,
|
||||
|
||||
RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM)
|
||||
MAX_CPU_FEATURE_INDEX
|
||||
@@ -447,6 +502,21 @@ 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
|
||||
@@ -459,6 +529,9 @@ 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,13 +282,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -356,7 +356,7 @@ instruct g1CompareAndExchangeP(iRegP mem_ptr, rarg5RegP oldval, iRegP_N2P newval
|
||||
|
||||
__ z_lgr($res$$Register, $oldval$$Register); // previous content
|
||||
|
||||
__ z_csg($oldval$$Register, $newval$$Register, 0, $mem_ptr$$reg);
|
||||
__ z_csg($res$$Register, $newval$$Register, 0, $mem_ptr$$reg);
|
||||
|
||||
write_barrier_post(masm, this,
|
||||
$mem_ptr$$Register /* store_addr */,
|
||||
|
||||
@@ -1980,11 +1980,6 @@ 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)) {
|
||||
|
||||
@@ -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 resolved, clinit_barrier_slow;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
@@ -2375,27 +2375,30 @@ void TemplateTable::resolve_cache_and_index_for_method(int byte_no,
|
||||
|
||||
__ load_method_entry(Rcache, index);
|
||||
__ z_cli(Address(Rcache, bc_offset), code);
|
||||
__ z_bre(resolved);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
__ bind(L_done);
|
||||
|
||||
BLOCK_COMMENT("} resolve_cache_and_index_for_method");
|
||||
}
|
||||
@@ -2408,7 +2411,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");
|
||||
|
||||
NearLabel resolved;
|
||||
Label L_clinit_barrier_slow, L_done;
|
||||
|
||||
Bytecodes::Code code = bytecode();
|
||||
switch (code) {
|
||||
@@ -2422,9 +2425,22 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
in_bytes(ResolvedFieldEntry::put_code_offset()) ;
|
||||
|
||||
__ z_cli(Address(cache, code_offset), code);
|
||||
__ z_bre(resolved);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
@@ -2432,7 +2448,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
|
||||
// Update registers with resolved info.
|
||||
__ load_field_entry(cache, index);
|
||||
|
||||
__ bind(resolved);
|
||||
__ bind(L_done);
|
||||
|
||||
BLOCK_COMMENT("} resolve_cache_and_index_for_field");
|
||||
}
|
||||
|
||||
@@ -425,6 +425,8 @@ class VM_Version: public Abstract_VM_Version {
|
||||
|
||||
constexpr static bool supports_secondary_supers_table() { return true; }
|
||||
|
||||
constexpr static bool supports_misaligned_vector_accesses() { return true; }
|
||||
|
||||
constexpr static bool supports_recursive_lightweight_locking() { return true; }
|
||||
|
||||
// CPU feature query functions
|
||||
|
||||
@@ -2225,6 +2225,44 @@ void Assembler::cvttss2sil(Register dst, XMMRegister src) {
|
||||
emit_int16(0x2C, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttss2sisl(Register dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttss2sisl(Register dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::evcvttss2sisq(Register dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttss2sisq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_32bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F3, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::cvttpd2dq(XMMRegister dst, XMMRegister src) {
|
||||
int vector_len = VM_Version::supports_avx512novl() ? AVX_512bit : AVX_128bit;
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
@@ -2310,6 +2348,25 @@ void Assembler::vcvttps2dq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
emit_int16(0x5B, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttps2dqs(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttps2dqs(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::vcvttpd2dq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
@@ -2317,6 +2374,25 @@ void Assembler::vcvttpd2dq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
emit_int16((unsigned char)0xE6, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttpd2dqs(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttpd2dqs(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_NONE, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::vcvtps2dq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(vector_len <= AVX_256bit ? VM_Version::supports_avx() : VM_Version::supports_evex(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
@@ -2332,6 +2408,25 @@ void Assembler::evcvttps2qq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
emit_int16(0x7A, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttps2qqs(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttps2qqs(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_HV, /* input_size_in_bits */ EVEX_32bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::evcvtpd2qq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx512dq(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
@@ -2356,6 +2451,25 @@ void Assembler::evcvttpd2qq(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
emit_int16(0x7A, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttpd2qqs(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttpd2qqs(XMMRegister dst, Address src, int vector_len) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::evcvtqq2pd(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||
assert(VM_Version::supports_avx512dq(), "");
|
||||
InstructionAttr attributes(vector_len, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
@@ -14988,6 +15102,44 @@ void Assembler::cvttsd2siq(Register dst, Address src) {
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::evcvttsd2sisl(Register dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttsd2sisl(Register dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::evcvttsd2sisq(Register dst, XMMRegister src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int16(0x6D, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::evcvttsd2sisq(Register dst, Address src) {
|
||||
assert(VM_Version::supports_avx10_2(), "");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_T1S, /* input_size_in_bits */ EVEX_64bit);
|
||||
attributes.set_is_evex_instruction();
|
||||
vex_prefix(src, 0, dst->encoding(), VEX_SIMD_F2, VEX_OPCODE_MAP5, &attributes);
|
||||
emit_int8((unsigned char)0x6D);
|
||||
emit_operand(dst, src, 0);
|
||||
}
|
||||
|
||||
void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
|
||||
InstructionAttr attributes(AVX_128bit, /* rex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ false);
|
||||
int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_F2, VEX_OPCODE_0F, &attributes);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user