From 55b40041d928fc541adef4c5358424c4403b8b61 Mon Sep 17 00:00:00 2001 From: panxuefeng Date: Wed, 13 Aug 2025 14:52:03 +0800 Subject: [PATCH] Loongson update to 23.0.1+11 --- LoongArch64-support.patch | 7213 ++++++++++++++++++++++++------------- openjdk-latest.spec | 5 +- 2 files changed, 4736 insertions(+), 2482 deletions(-) diff --git a/LoongArch64-support.patch b/LoongArch64-support.patch index 80a93bd..f379528 100644 --- a/LoongArch64-support.patch +++ b/LoongArch64-support.patch @@ -1,5 +1,423 @@ +diff --git a/.workflow/submit.yml b/.workflow/submit.yml +new file mode 100644 +index 00000000000..e857a10aa5f +--- /dev/null ++++ b/.workflow/submit.yml +@@ -0,0 +1,365 @@ ++// ++// Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. ++// Copyright (c) 2020, 2022, Loongson Technology. 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. ++// ++ ++pipeline { ++ agent any ++ environment { ++ REPO_NAME="${GERRIT_PROJECT}" ++ } ++ stages { ++ stage('Build') { ++ matrix { ++ axes { ++ axis { ++ name 'ARCH' ++ values 'x86_64', 'loongarch64' ++ } ++ axis { ++ name 'JVMVARIANT' ++ values 'server', 'zero' ++ } ++ axis { ++ name 'DEBUGLEVEL' ++ values 'release', 'fastdebug', 'slowdebug' ++ } ++ axis { ++ name 'WITH_JFX' ++ //values 'nofx', 'fx' ++ values 'nofx' ++ } ++ } ++ excludes { ++ exclude { ++ axis { ++ name 'DEBUGLEVEL' ++ values 'slowdebug' ++ } ++ } ++ exclude { ++ axis { ++ name 'JVMVARIANT' ++ values 'zero' ++ } ++ } ++ exclude { ++ axis { ++ name 'ARCH' ++ values 'mips64el' ++ } ++ axis { ++ name 'JVMVARIANT' ++ values 'zero' ++ } ++ } ++ } ++ stages { ++ stage('build JDK') { ++ agent { label getBuildName(ARCH) } ++ environment { ++ artifact_name = "${REPO_NAME}-internal-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}-bin" ++ } ++ steps { ++ // prepare boot-jdk ++ echo "Do Build for ${ARCH}-${JVMVARIANT}-${DEBUGLEVEL} @${env.NODE_NAME} ${env.WORKSPACE}" ++ dir("${env.WORKSPACE}/${REPO_NAME}"){ ++ sh ''' ++ arch=`uname -m` ++ if [ "$arch" = "mips64" ] || [ "$arch" = "mips64el" ]; then ++ arch=mips64 ++ fi ++ ++ BOOT_JDK_URL=$(grep LINUX_${arch}_BOOT_JDK_URL .workflow/test-dependencies | awk -F "=" '{print $2}') ++ ++ if [ -z ${BOOT_JDK_URL} ]; then ++ echo "BOOT_JDK_URL does not exist" ++ exit 2 ++ fi ++ ++ BOOT_JDK_IMAGE_NAME=boot_jdk_image_name ++ rm -rf ${BOOT_JDK_IMAGE_NAME} ++ mkdir ${BOOT_JDK_IMAGE_NAME} ++ wget -q ${BOOT_JDK_URL} -O ${WORKSPACE}/jdk.tar.gz ++ tar xzf ${WORKSPACE}/jdk.tar.gz --strip-components 1 -C ${BOOT_JDK_IMAGE_NAME} ++ rm -rf ${WORKSPACE}/jdk.tar.gz ++ ./${BOOT_JDK_IMAGE_NAME}/bin/java -version ++ if [ $? -ne 0 ]; then ++ echo "BOOT_JDK_IMAGE_NAME does not exist" ++ exit 2 ++ fi ++ ++ export GTEST_IMAGE_NAME=googletest-release-1.8.1 ++ rm -rf ${GTEST_IMAGE_NAME}* ++ curl -sL ftp://10.2.5.13/${GTEST_IMAGE_NAME}.tar.gz | tar xzf - ++ commit_head=`git rev-parse HEAD` ++ if grep "Loongnix release 1.0" /etc/issue || grep "CentOS Linux release 7" /etc/redhat-release; then ++ # gcc of Loongnix 1.0/CentOS 7 is too old for jdk-ls, use devtoolset-7-gcc ++ if [ -f /opt/rh/devtoolset-7/enable ]; then ++ source /opt/rh/devtoolset-7/enable ++ else ++ echo "Warning: /opt/rh/devtoolset-7/enable not found, try to yum install devtoolset-7-gcc devtoolset-7-gcc-c++" ++ fi ++ fi ++ rm -rf build ++ if [ x"${WITH_JFX}" = x"fx" ]; then ++ JFX_URL=$(grep ${arch}_JAVAFX_ZIP_URL .workflow/test-dependencies | awk -F "=" '{print $2}') ++ echo "Using JFX: $JFX_URL" ++ rm -rf modular-sdk* ++ wget -q $JFX_URL -O modular-sdk.tar.gz ++ tar xzf modular-sdk.tar.gz ++ rm -rf modular-sdk.tar.gz ++ ++ jfx_sdk_dir=modular-sdk ++ CONF_PAR_EXTRA="${CONF_PAR_EXTRA} --with-import-modules=$jfx_sdk_dir" ++ fi ++ ++ bash configure \ ++ --with-debug-level=${DEBUGLEVEL} \ ++ --with-jvm-variants=${JVMVARIANT} \ ++ --with-boot-jdk=${BOOT_JDK_IMAGE_NAME} \ ++ --with-gtest=${GTEST_IMAGE_NAME} \ ++ --disable-warnings-as-errors \ ++ --with-version-opt="presubmit-${commit_head}" \ ++ ${CONF_PAR_EXTRA} --with-default-make-target="product-bundles test-bundles" ++ make CONF=linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL} ++ ''' ++ } ++ // pack jdk ++ dir("${env.WORKSPACE}/${REPO_NAME}/build/linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}/images"){ ++ stash name: "${REPO_NAME}-internal-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}-bin", includes: "jdk/**/*" ++ } ++ // pack tests ++ dir("${env.WORKSPACE}/${REPO_NAME}/build/linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}/images"){ ++ stash name: "${REPO_NAME}-internal-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}-bin-tests", includes: "test/**/*" ++ } ++ } ++ } ++ } ++ } ++ } // stage('Build') ++ ++ stage('Test') { ++ matrix { ++ axes { ++ axis { ++ name 'ARCH' ++ values 'x86_64', 'loongarch64' ++ } ++ axis { ++ name 'JVMVARIANT' ++ values 'server', 'zero' ++ } ++ axis { ++ name 'DEBUGLEVEL' ++ values 'release', 'fastdebug' ++ } ++ axis { ++ name 'WITH_JFX' ++ //values 'nofx', 'fx' ++ values 'nofx' ++ } ++ // loongarch64 use splitted test group for better parallel execution, x64 don't ++ axis { ++ name 'TARGET' ++ values 'hotspot:tier1_common', 'hotspot:tier1_compiler', 'hotspot:tier1_gc', 'hotspot:tier1_runtime', 'hotspot:tier1_serviceability', 'jdk:tier1_part1', 'jdk:tier1_part2', 'jdk:tier1_part3', 'langtools:tier1', ++ 'tier1' ++ } ++ } ++ excludes { ++ exclude { ++ axis { ++ name 'JVMVARIANT' ++ notValues 'server' ++ } ++ } ++ exclude { ++ axis { ++ name 'ARCH' ++ values 'loongarch64' ++ } ++ axis { ++ name 'TARGET' ++ values 'tier1' ++ } ++ } ++ exclude { ++ axis { ++ name 'ARCH' ++ values 'x86_64' ++ } ++ axis { ++ name 'TARGET' ++ values 'hotspot:tier1_common', 'hotspot:tier1_compiler', 'hotspot:tier1_gc', 'hotspot:tier1_runtime', 'hotspot:tier1_serviceability', 'jdk:tier1_part1', 'jdk:tier1_part2', 'jdk:tier1_part3', 'langtools:tier1' ++ } ++ } ++ } ++ stages { ++ stage('jtreg test') { ++ agent { label getTestName(ARCH) } ++ steps { ++ echo "Do JTreg ${TARGET} Tests for ${ARCH}-${JVMVARIANT}-${DEBUGLEVEL} @${env.NODE_NAME} ${env.WORKSPACE}" ++ // unstash jdk ++ dir("${env.WORKSPACE}/jdk_to_test") { ++ sh "rm -rf *" ++ unstash "${REPO_NAME}-internal-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}-bin" ++ unstash "${REPO_NAME}-internal-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}-bin-tests" ++ } ++ // prepare jtreg ++ sh ''' ++ rm -rf jtreg ++ JTREG_VERSION=$(grep JTREG_VERSION ${REPO_NAME}/make/conf/test-dependencies | awk -F "=" '{print $2}') ++ JTREG_BUILD=$(grep JTREG_BUILD ${REPO_NAME}/make/conf/test-dependencies | awk -F "=" '{print $2}') ++ if [ ! -z `echo "$JTREG_BUILD" | grep -E "b[0-9]{2}"` ]; then ++ linkSymbol="-" ++ elif [ ! -z `echo "$JTREG_BUILD" | grep -E "^[0-9]+$"` ]; then ++ linkSymbol="+" ++ else ++ linkSymbol="" ++ fi ++ jtreg_tar_name=jtreg-${JTREG_VERSION}${linkSymbol}${JTREG_BUILD}.tar.gz ++ curl -sL ftp://10.2.5.13/${jtreg_tar_name} | tar xzf - && ./jtreg/bin/jtreg ++ ''' ++ // run tests ++ sh "rm -rf out; mkdir out" ++ dir("${env.WORKSPACE}/${REPO_NAME}") { ++ // for debug ++ sh "rm -rf ${REPO_NAME}/build/run-test-prebuilt; echo WORKSPACE: ${WORKSPACE}" ++ sh ''' ++ export LANG="en_US" ++ ${WORKSPACE}/jdk_to_test/jdk/bin/java -version ++ ls ${WORKSPACE}/jdk_to_test/test ++ rm -rf build ++ JDK_IMAGE_DIR=${WORKSPACE}/jdk_to_test/jdk \ ++ TEST_IMAGE_DIR=${WORKSPACE}/jdk_to_test/test \ ++ BOOT_JDK=${WORKSPACE}/jdk_to_test/jdk \ ++ JT_HOME=${WORKSPACE}/jtreg \ ++ make test-prebuilt \ ++ CONF_NAME=run-test-prebuilt \ ++ LOG_CMDLINES=true \ ++ JTREG_VERBOSE=fail,error,time \ ++ TEST="${TARGET}" \ ++ TEST_OPTS_JAVA_OPTIONS= \ ++ JTREG_KEYWORDS="!headful" \ ++ JTREG="JAVA_OPTIONS=-XX:-CreateCoredumpOnCrash;RETRY_COUNT=2;TIMEOUT_FACTOR=10" ++ ''' ++ } ++ // Check that all tests executed successfully ++ dir("${env.WORKSPACE}/${REPO_NAME}") { ++ script { ++ try { ++ sh ''' ++ export TARGET_name=`echo $TARGET | sed "s#:#-#g;s#/#-#g"` ++ export TESTS_FAILED="false" ++ if ! grep --include=test-summary.txt -lqr build/*/test-results -e "TEST SUCCESS" ; then ++ cat build/*/test-results/*/text/newfailures.txt ; ++ cat build/*/test-results/*/text/other_errors.txt ; ++ cat build/*/test-results/*/text/newfailures.txt > ${WORKSPACE}/out/fail_or_error_list_linux-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}.txt; ++ cat build/*/test-results/*/text/other_errors.txt >> ${WORKSPACE}/out/fail_or_error_list_linux-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}.txt; ++ TESTS_FAILED="true" ++ fi ++ cd ${WORKSPACE}/${REPO_NAME}/build/run-test-prebuilt/test-results/ ++ zip -r9 \ ++ "${WORKSPACE}/out/linux-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}_testresults.zip" \ ++ . ++ cd - ++ cd ${WORKSPACE}/${REPO_NAME}/build/run-test-prebuilt/test-support/ ++ zip -r9 \ ++ "${WORKSPACE}/out/linux-${ARCH}-${WITH_JFX}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}_testsupport.zip" \ ++ . -i *.jtr -i */hs_err*.log -i */replay*.log ++ cd - ++ if ! find . -name "hs_err_pid*" -type f ; then ++ mkdir -p ${WORKSPACE}/out/crash_linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}/ ++ find . -name "hs_err_pid*" -type f | xargs -l cp {} ${WORKSPACE}/out/crash_linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}/ ++ fi ++ if [ "$TESTS_FAILED" = "true" ]; then ++ exit 2 ++ fi ++ ''' ++ } catch (ex) { ++ unstable('tests failed!') ++ } ++ } ++ } ++ // // Package test results ++ // dir("${env.WORKSPACE}/${REPO_NAME}/build/run-test-prebuilt/test-results/") { ++ // sh ''' ++ // echo "$TESTS_FAILED" ++ // zip -r9 \ ++ // "${WORKSPACE}/out/linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}_testresults.zip" \ ++ // . ++ // ''' ++ // } ++ // // Package test support ++ // dir("${env.WORKSPACE}/${REPO_NAME}/build/run-test-prebuilt/test-support/") { ++ // sh ''' ++ // zip -r9 \ ++ // "${WORKSPACE}/out/linux-${ARCH}-${JVMVARIANT}-${DEBUGLEVEL}_${TARGET_name}_testsupport.zip" \ ++ // . -i *.jtr -i */hs_err*.log -i */replay*.log ++ // ''' ++ // } ++ // dir("${env.WORKSPACE}/${REPO_NAME}") { ++ // sh ''' ++ // if [ "$TESTS_FAILED" = "true" ]; then ++ // exit 1 ; ++ // fi ++ // ''' ++ // } ++ } ++ post { ++ always { ++ echo 'This will always run' ++ sh ''' ++ rm -rf ${WORKSPACE}/jdk_to_test* ++ rm -rf ${WORKSPACE}/${REPO_NAME}* ++ ls ++ ''' ++ archiveArtifacts artifacts: 'out/**/*', followSymlinks: false ++ } ++ } ++ } ++ } ++ } ++ } // stage('Test') ++ ++ } // stages ++} ++ ++def getBuildName(archName) { ++ if("loongarch64".equals(archName)) { ++ return "loongarch64"; ++ } else if ("x86_64".equals(archName)) { ++ return "el8-x86"; ++ } else { ++ return "unknown"; ++ } ++} ++ ++def getTestName(archName) { ++ if("loongarch64".equals(archName)) { ++ return "loongarch64"; ++ } else if ("x86_64".equals(archName)) { ++ return "el8-x86"; ++ } else { ++ return "unknown"; ++ } ++} +diff --git a/.workflow/test-dependencies b/.workflow/test-dependencies +new file mode 100644 +index 00000000000..7c152a90632 +--- /dev/null ++++ b/.workflow/test-dependencies +@@ -0,0 +1,41 @@ ++# ++# Copyright (c) 2022, 2024, Loongson Technology. 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. ++# ++ ++LINUX_loongarch64_BOOT_JDK_URL=ftp://10.2.5.13/pub/jdk22u-ls-loongarch64-fx-server-release-ls-jdk-22+36-0.tar.gz ++LINUX_loongarch64nw_BOOT_JDK_URL=ftp://10.2.5.13/pub/jdk22u-ls-loongarch64nw-server-release-ls-jdk-22+36-0.tar.gz ++LINUX_mips64_BOOT_JDK_URL=ftp://10.2.5.13/jdk22u-lnd20-mips64-zero-release-098.tar.gz ++LINUX_x86_64_BOOT_JDK_URL=ftp://10.2.5.13/openjdk-22_linux-x64_bin.tar.gz ++LINUX_aarch64_BOOT_JDK_URL=ftp://10.2.5.13/openjdk-22_linux-aarch64_bin.tar.gz ++ ++# JAVAFX_ZIP download locations for dependencies used by jdk build. ++ ++loongarch64_JAVAFX_ZIP_URL=ftp://10.2.5.13/pub/jfx/jdk17/jfx21u-ls-modular-sdk-Release-21.0.3+200-lnd20-loongarch64.tar.gz ++loongarch64_JAVAFX_ZIP_SHA256SUM=871017360ca2264398eafe5b923fad3e861386d381b78cbf6bd3a0b0b184de95 ++loongarch64nw_JAVAFX_ZIP_URL=ftp://10.2.5.13/pub/jfx/jdk17/jfx21u-ls-modular-sdk-Release-21.0.3+200-loongarch64nw-build.tar.gz ++loongarch64nw_JAVAFX_ZIP_SHA256SUM=45da86607972f260197c1a55685937afdcddd1069dbbb1466581b3983d81e04c ++mips64_JAVAFX_ZIP_URL=ftp://10.2.5.13/pub/jfx/jdk17/jfx21u-ls-modular-sdk-Release-21.0.3+200-lnd20-mips64.tar.gz ++mips64_JAVAFX_ZIP_SHA256SUM=9531c20318b39476473b575e9e91209a4cefd57e71c12751f701f0b01eb328f0 ++x86_64_JAVAFX_ZIP_URL=ftp://10.2.5.13/pub/jfx/jdk17/jfx21u-ls-modular-sdk-Release-21.0.3+200-x86-f29-build.tar.gz ++x86_64_JAVAFX_ZIP_SHA256SUM=0f1f285028d1c88375d5f34cd46d8224536ba98740ab6f7c4d074d64a55cd909 ++aarch64_JAVAFX_ZIP_URL=ftp://10.2.5.13/pub/jfx/jdk17/jfx21u-ls-modular-sdk-Release-21.0.3+200-kp920-1way-debian10-01.tar.gz ++aarch64_JAVAFX_ZIP_SHA256SUM=d9a9b46f4f47006078700b9a75834eee2245a8c67aa01efc254acef635afc298 diff --git a/make/autoconf/jvm-features.m4 b/make/autoconf/jvm-features.m4 -index 28801984862..c37c5c27429 100644 +index bdf92d701b9..8b3d7b0e128 100644 --- a/make/autoconf/jvm-features.m4 +++ b/make/autoconf/jvm-features.m4 @@ -23,6 +23,12 @@ @@ -34,7 +452,7 @@ index 28801984862..c37c5c27429 100644 AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, $OPENJDK_TARGET_CPU]) -@@ -358,6 +367,13 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_ZGC], +@@ -342,6 +351,13 @@ AC_DEFUN_ONCE([JVM_FEATURES_CHECK_ZGC], AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) AVAILABLE=false fi @@ -1093,13 +1511,13 @@ index 00000000000..f9528680cf0 +} diff --git a/src/hotspot/cpu/loongarch/assembler_loongarch.hpp b/src/hotspot/cpu/loongarch/assembler_loongarch.hpp new file mode 100644 -index 00000000000..a4ee680663d +index 00000000000..f57ce474bed --- /dev/null +++ b/src/hotspot/cpu/loongarch/assembler_loongarch.hpp @@ -0,0 +1,3213 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -2852,15 +3270,15 @@ index 00000000000..a4ee680663d + // Test if x is within signed immediate range for nbits. + static bool is_simm (int x, unsigned int nbits) { + assert(0 < nbits && nbits < 32, "out of bounds"); -+ const int min = -( ((int)1) << nbits-1 ); -+ const int maxplus1 = ( ((int)1) << nbits-1 ); ++ const int min = -( ((int)1) << (nbits-1) ); ++ const int maxplus1 = ( ((int)1) << (nbits-1) ); + return min <= x && x < maxplus1; + } + + static bool is_simm(jlong x, unsigned int nbits) { + assert(0 < nbits && nbits < 64, "out of bounds"); -+ const jlong min = -( ((jlong)1) << nbits-1 ); -+ const jlong maxplus1 = ( ((jlong)1) << nbits-1 ); ++ const jlong min = -( ((jlong)1) << (nbits-1) ); ++ const jlong maxplus1 = ( ((jlong)1) << (nbits-1) ); + return min <= x && x < maxplus1; + } + @@ -5434,13 +5852,13 @@ index 00000000000..f157536797b +} diff --git a/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp new file mode 100644 -index 00000000000..2d489e691b9 +index 00000000000..6efa280b970 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch.hpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -5509,8 +5927,8 @@ index 00000000000..2d489e691b9 + void emit_cmp_branch(LIR_OpBranch* op); + + enum { -+ // call stub: CompiledStaticCall::to_interp_stub_size() + -+ // CompiledStaticCall::to_trampoline_stub_size() ++ // call stub: CompiledDirectCall::to_interp_stub_size() + ++ // CompiledDirectCall::to_trampoline_stub_size() + _call_stub_size = 13 * NativeInstruction::nop_instruction_size, + _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(175), + _deopt_handler_size = 7 * NativeInstruction::nop_instruction_size @@ -5524,13 +5942,13 @@ index 00000000000..2d489e691b9 +#endif // CPU_LOONGARCH_C1_LIRASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp new file mode 100644 -index 00000000000..1cea5b84c0f +index 00000000000..538a3101881 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp -@@ -0,0 +1,3365 @@ +@@ -0,0 +1,3340 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -5781,35 +6199,7 @@ index 00000000000..1cea5b84c0f + +// inline cache check; done before the frame is built. +int LIR_Assembler::check_icache() { -+ Register receiver = FrameMap::receiver_opr->as_register(); -+ Register ic_klass = IC_Klass; -+ int start_offset = __ offset(); -+ Label dont; -+ -+ __ verify_oop(receiver); -+ -+ // explicit null check not needed since load from [klass_offset] causes a trap -+ // check against inline cache -+ assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), -+ "must add explicit null check"); -+ -+ __ load_klass(SCR2, receiver); -+ __ beq(SCR2, ic_klass, dont); -+ -+ // if icache check fails, then jump to runtime routine -+ // Note: RECEIVER must still contain the receiver! -+ __ jmp(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); -+ -+ // We align the verified entry point unless the method body -+ // (including its inline cache check) will fit in a single 64-byte -+ // icache line. -+ if (!method()->is_accessor() || __ offset() - start_offset > 4 * 4) { -+ // force alignment after the cache check. -+ __ align(CodeEntryAlignment); -+ } -+ -+ __ bind(dont); -+ return start_offset; ++ return __ ic_check(CodeEntryAlignment); +} + +void LIR_Assembler::clinit_barrier(ciMethod* method) { @@ -6751,10 +7141,11 @@ index 00000000000..1cea5b84c0f + __ move(tmp3, len); + } + __ allocate_array(op->obj()->as_register(), len, tmp1, tmp2, -+ arrayOopDesc::header_size(op->type()), ++ arrayOopDesc::base_offset_in_bytes(op->type()), + array_element_size(op->type()), + op->klass()->as_register(), -+ *op->stub()->entry()); ++ *op->stub()->entry(), ++ op->zero_array()); + } + __ bind(*op->stub()->continuation()); +} @@ -7864,7 +8255,7 @@ index 00000000000..1cea5b84c0f + // This is recognized as unresolved by relocs/nativeInst/ic code + __ patchable_jump(__ pc()); + -+ assert(__ offset() - start + CompiledStaticCall::to_trampoline_stub_size() <= call_stub_size(), ++ assert(__ offset() - start + CompiledDirectCall::to_trampoline_stub_size() <= call_stub_size(), + "stub too big"); + __ end_a_stub(); +} @@ -8330,7 +8721,9 @@ index 00000000000..1cea5b84c0f + __ call_VM_leaf(entry, 3); + } + -+ __ bind(*stub->continuation()); ++ if (stub != nullptr) { ++ __ bind(*stub->continuation()); ++ } +} + +void LIR_Assembler::emit_lock(LIR_OpLock* op) { @@ -8561,7 +8954,7 @@ index 00000000000..1cea5b84c0f + // set already but no need to check. + __ beqz(SCR1, next); + -+ __ andi(SCR1, tmp, TypeEntries::type_unknown); ++ __ test_bit(SCR1, tmp, exact_log2(TypeEntries::type_unknown)); + __ bnez(SCR1, next); // already unknown. Nothing to do anymore. + + if (TypeEntries::is_type_none(current_klass)) { @@ -8584,7 +8977,7 @@ index 00000000000..1cea5b84c0f + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); + + __ ld_d(tmp, mdo_addr); -+ __ andi(SCR2, tmp, TypeEntries::type_unknown); ++ __ test_bit(SCR1, tmp, exact_log2(TypeEntries::type_unknown)); + __ bnez(SCR2, next); // already unknown. Nothing to do anymore. + } + @@ -8647,7 +9040,7 @@ index 00000000000..1cea5b84c0f + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); + + __ ld_d(tmp, mdo_addr); -+ __ andi(SCR1, tmp, TypeEntries::type_unknown); ++ __ test_bit(SCR1, tmp, exact_log2(TypeEntries::type_unknown)); + __ bnez(SCR1, next); // already unknown. Nothing to do anymore. + + __ ori(tmp, tmp, TypeEntries::type_unknown); @@ -8895,10 +9288,10 @@ index 00000000000..1cea5b84c0f +#undef __ diff --git a/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp new file mode 100644 -index 00000000000..bf5fba7a100 +index 00000000000..16feea2bd5b --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp -@@ -0,0 +1,1393 @@ +@@ -0,0 +1,1408 @@ +/* + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Loongson Technology. All rights reserved. @@ -9761,7 +10154,13 @@ index 00000000000..bf5fba7a100 + assert(x->number_of_arguments() == 5, "wrong type"); + + // Make all state_for calls early since they can emit code -+ CodeEmitInfo* info = state_for(x, x->state()); ++ CodeEmitInfo* info = nullptr; ++ if (x->state_before() != nullptr && x->state_before()->force_reexecute()) { ++ info = state_for(x, x->state_before()); ++ info->set_force_reexecute(); ++ } else { ++ info = state_for(x, x->state()); ++ } + + LIRItem src(x->argument_at(0), this); + LIRItem src_pos(x->argument_at(1), this); @@ -9794,6 +10193,9 @@ index 00000000000..bf5fba7a100 + int flags; + ciArrayKlass* expected_type; + arraycopy_helper(x, &flags, &expected_type); ++ if (x->check_flag(Instruction::OmitChecksFlag)) { ++ flags = 0; ++ } + + __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(), + length.result(), tmp, expected_type, flags, info); // does add_safepoint @@ -10029,7 +10431,13 @@ index 00000000000..bf5fba7a100 +} + +void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { -+ CodeEmitInfo* info = state_for(x, x->state()); ++ CodeEmitInfo* info = nullptr; ++ if (x->state_before() != nullptr && x->state_before()->force_reexecute()) { ++ info = state_for(x, x->state_before()); ++ info->set_force_reexecute(); ++ } else { ++ info = state_for(x, x->state()); ++ } + + LIRItem length(x->length(), this); + length.load_item_force(FrameMap::s0_opr); @@ -10046,7 +10454,7 @@ index 00000000000..bf5fba7a100 + __ metadata2reg(ciTypeArrayKlass::make(elem_type)->constant_encoding(), klass_reg); + + CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); -+ __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path); ++ __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path, x->zero_array()); + + LIR_Opr result = rlock_result(x); + __ move(reg, result); @@ -10472,13 +10880,13 @@ index 00000000000..219b2e3671c +} diff --git a/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp new file mode 100644 -index 00000000000..d1c63b13896 +index 00000000000..78bb6eb7fa5 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch.hpp -@@ -0,0 +1,111 @@ +@@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -10566,14 +10974,15 @@ index 00000000000..d1c63b13896 + }; + + // allocation of arrays -+ // obj : will contain pointer to allocated object -+ // len : array length in number of elements -+ // t : scratch register - contents destroyed -+ // header_size: size of object header in words -+ // f : element scale factor -+ // slow_case : exit to slow case implementation if fast allocation fails -+ void allocate_array(Register obj, Register len, Register t, Register t2, int header_size, -+ int f, Register klass, Label& slow_case); ++ // obj : will contain pointer to allocated object ++ // len : array length in number of elements ++ // t : scratch register - contents destroyed ++ // base_offset_in_bytes: offset of first array element, in bytes ++ // f : element scale factor ++ // slow_case : exit to slow case implementation if fast allocation fails ++ // zero_array : zero the allocated array or not ++ void allocate_array(Register obj, Register len, Register t, Register t2, int base_offset_in_bytes, ++ int f, Register klass, Label& slow_case, bool zero_array); + + int rsp_offset() const { return _rsp_offset; } + void set_rsp_offset(int n) { _rsp_offset = n; } @@ -10589,13 +10998,13 @@ index 00000000000..d1c63b13896 +#endif // CPU_LOONGARCH_C1_MACROASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp new file mode 100644 -index 00000000000..eaaaf464fe6 +index 00000000000..102a1cdf634 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp -@@ -0,0 +1,350 @@ +@@ -0,0 +1,356 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -10648,17 +11057,16 @@ index 00000000000..eaaaf464fe6 + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(hdr, obj); + ld_w(hdr, Address(hdr, Klass::access_flags_offset())); -+ li(SCR1, JVM_ACC_IS_VALUE_BASED_CLASS); -+ andr(SCR1, hdr, SCR1); ++ test_bit(SCR1, hdr, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS)); + bnez(SCR1, slow_case); + } + -+ // Load object header -+ ld_d(hdr, Address(obj, hdr_offset)); + if (LockingMode == LM_LIGHTWEIGHT) { + lightweight_lock(obj, hdr, SCR1, SCR2, slow_case); + } else if (LockingMode == LM_LEGACY) { + Label done; ++ // Load object header ++ ld_d(hdr, Address(obj, hdr_offset)); + // and mark it as unlocked + ori(hdr, hdr, markWord::unlocked_value); + // save unlocked object header into the displaced header location on the stack @@ -10715,11 +11123,6 @@ index 00000000000..eaaaf464fe6 + ld_d(obj, Address(disp_hdr, BasicObjectLock::obj_offset())); + verify_oop(obj); + if (LockingMode == LM_LIGHTWEIGHT) { -+ ld_d(hdr, Address(obj, oopDesc::mark_offset_in_bytes())); -+ // We cannot use tbnz here, the target might be too far away and cannot -+ // be encoded. -+ andi(AT, hdr, markWord::monitor_value); -+ bnez(AT, slow_case); + lightweight_unlock(obj, hdr, SCR1, SCR2, slow_case); + } else if (LockingMode == LM_LEGACY) { + // test if object header is pointing to the displaced header, and if so, restore @@ -10766,6 +11169,12 @@ index 00000000000..eaaaf464fe6 + + if (len->is_valid()) { + st_w(len, Address(obj, arrayOopDesc::length_offset_in_bytes())); ++ int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt; ++ if (!is_aligned(base_offset, BytesPerWord)) { ++ assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned"); ++ // Clear gap/first 4 bytes following the length field. ++ st_w(R0, Address(obj, base_offset)); ++ } + } else if (UseCompressedClassPointers) { + store_klass_gap(obj, R0); + } @@ -10847,7 +11256,8 @@ index 00000000000..eaaaf464fe6 +} + +void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, -+ int header_size, int f, Register klass, Label& slow_case) { ++ int base_offset_in_bytes, int f, Register klass, ++ Label& slow_case, bool zero_array) { + assert_different_registers(obj, len, t1, t2, klass); + + // determine alignment mask @@ -10859,7 +11269,7 @@ index 00000000000..eaaaf464fe6 + + const Register arr_size = t2; // okay to be the same + // align object end -+ li(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask); ++ li(arr_size, (int32_t)base_offset_in_bytes + MinObjAlignmentInBytesMask); + slli_w(SCR1, len, f); + add_d(arr_size, arr_size, SCR1); + bstrins_d(arr_size, R0, exact_log2(MinObjAlignmentInBytesMask + 1) - 1, 0); @@ -10868,8 +11278,13 @@ index 00000000000..eaaaf464fe6 + + initialize_header(obj, klass, len, t1, t2); + ++ // Align-up to word boundary, because we clear the 4 bytes potentially ++ // following the length field in initialize_header(). ++ int base_offset = align_up(base_offset_in_bytes, BytesPerWord); + // clear rest of allocated space -+ initialize_body(obj, arr_size, header_size * BytesPerWord, t1, t2); ++ if (zero_array) { ++ initialize_body(obj, arr_size, base_offset, t1, t2); ++ } + + membar(StoreStore); + @@ -10945,13 +11360,13 @@ index 00000000000..eaaaf464fe6 +#endif // ifndef PRODUCT diff --git a/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp b/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp new file mode 100644 -index 00000000000..21f7c6f2d00 +index 00000000000..f587ae722df --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp -@@ -0,0 +1,1049 @@ +@@ -0,0 +1,1047 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -10989,7 +11404,6 @@ index 00000000000..21f7c6f2d00 +#include "interpreter/interpreter.hpp" +#include "memory/universe.hpp" +#include "nativeInst_loongarch.hpp" -+#include "oops/compiledICHolder.hpp" +#include "oops/oop.inline.hpp" +#include "prims/jvmtiExport.hpp" +#include "register_loongarch.hpp" @@ -11723,8 +12137,7 @@ index 00000000000..21f7c6f2d00 + Register t = A5; + __ load_klass(t, A0); + __ ld_w(t, Address(t, Klass::access_flags_offset())); -+ __ li(SCR1, JVM_ACC_HAS_FINALIZER); -+ __ andr(SCR1, t, SCR1); ++ __ test_bit(SCR1, t, exact_log2(JVM_ACC_HAS_FINALIZER)); + __ bnez(SCR1, register_finalizer); + __ jr(RA); + @@ -12167,13 +12580,13 @@ index 00000000000..37b74d4ac16 +#undef __ diff --git a/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.cpp new file mode 100644 -index 00000000000..d83d08e9549 +index 00000000000..7adcad865f5 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.cpp -@@ -0,0 +1,1903 @@ +@@ -0,0 +1,2466 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -12206,7 +12619,13 @@ index 00000000000..d83d08e9549 +#include "opto/subnode.hpp" +#include "runtime/objectMonitor.hpp" +#include "runtime/stubRoutines.hpp" ++#include "utilities/globalDefinitions.hpp" + ++#ifdef PRODUCT ++#define BLOCK_COMMENT(str) /* nothing */ ++#else ++#define BLOCK_COMMENT(str) block_comment(str) ++#endif + +// using the cr register as the bool result: 0 for failed; others success. +void C2_MacroAssembler::fast_lock_c2(Register oop, Register box, Register flag, @@ -12215,6 +12634,7 @@ index 00000000000..d83d08e9549 + Label object_has_monitor; + Label count, no_count; + ++ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_lock_lightweight"); + assert_different_registers(oop, box, tmp, disp_hdr, flag); + + // Load markWord from object into displaced_header. @@ -12224,20 +12644,20 @@ index 00000000000..d83d08e9549 + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(flag, oop); + ld_wu(flag, Address(flag, Klass::access_flags_offset())); -+ li(AT, JVM_ACC_IS_VALUE_BASED_CLASS); -+ andr(AT, flag, AT); ++ test_bit(AT, flag, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS)); + move(flag, R0); + bnez(AT, cont); + } + + // Check for existing monitor -+ andi(AT, disp_hdr, markWord::monitor_value); ++ test_bit(AT, disp_hdr, exact_log2(markWord::monitor_value)); + bnez(AT, object_has_monitor); // inflated vs stack-locked|neutral|bias + + if (LockingMode == LM_MONITOR) { + move(flag, R0); // Set zero flag to indicate 'failure' + b(cont); -+ } else if (LockingMode == LM_LEGACY) { ++ } else { ++ assert(LockingMode == LM_LEGACY, "must be"); + // Set tmp to be (markWord of object | UNLOCK_VALUE). + ori(tmp, disp_hdr, markWord::unlocked_value); + @@ -12264,10 +12684,6 @@ index 00000000000..d83d08e9549 + st_d(tmp, box, BasicLock::displaced_header_offset_in_bytes()); + sltui(flag, tmp, 1); // flag = (tmp == 0) ? 1 : 0 + b(cont); -+ } else { -+ assert(LockingMode == LM_LIGHTWEIGHT, "must be"); -+ lightweight_lock(oop, disp_hdr, flag, SCR1, no_count); -+ b(count); + } + + // Handle existing monitor. @@ -12280,14 +12696,14 @@ index 00000000000..d83d08e9549 + move(AT, R0); + addi_d(tmp, disp_hdr, in_bytes(ObjectMonitor::owner_offset()) - markWord::monitor_value); + cmpxchg(Address(tmp, 0), AT, TREG, flag, true, true /* acquire */); -+ if (LockingMode != LM_LIGHTWEIGHT) { -+ // Store a non-null value into the box to avoid looking like a re-entrant -+ // lock. The fast-path monitor unlock code checks for -+ // markWord::monitor_value so use markWord::unused_mark which has the -+ // relevant bit set, and also matches ObjectSynchronizer::enter. -+ li(tmp, (address)markWord::unused_mark().value()); -+ st_d(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ } ++ ++ // Store a non-null value into the box to avoid looking like a re-entrant ++ // lock. The fast-path monitor unlock code checks for ++ // markWord::monitor_value so use markWord::unused_mark which has the ++ // relevant bit set, and also matches ObjectSynchronizer::enter. ++ li(tmp, (address)markWord::unused_mark().value()); ++ st_d(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); ++ + bnez(flag, cont); // CAS success means locking succeeded + + bne(AT, TREG, cont); // Check for recursive locking @@ -12314,6 +12730,7 @@ index 00000000000..d83d08e9549 + Label object_has_monitor; + Label count, no_count; + ++ assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight"); + assert_different_registers(oop, box, tmp, disp_hdr, flag); + + // Find the lock address and load the displaced header from the stack. @@ -12329,22 +12746,19 @@ index 00000000000..d83d08e9549 + + // Handle existing monitor. + ld_d(tmp, oop, oopDesc::mark_offset_in_bytes()); -+ andi(AT, tmp, markWord::monitor_value); ++ test_bit(AT, tmp, exact_log2(markWord::monitor_value)); + bnez(AT, object_has_monitor); + + if (LockingMode == LM_MONITOR) { + move(flag, R0); // Set zero flag to indicate 'failure' + b(cont); -+ } else if (LockingMode == LM_LEGACY) { ++ } else { ++ assert(LockingMode == LM_LEGACY, "must be"); + // Check if it is still a light weight lock, this is true if we + // see the stack address of the basicLock in the markWord of the + // object. + cmpxchg(Address(oop, 0), box, disp_hdr, flag, false, false /* acquire */); + b(cont); -+ } else { -+ assert(LockingMode == LM_LIGHTWEIGHT, "must be"); -+ lightweight_unlock(oop, tmp, flag, box, no_count); -+ b(count); + } + + // Handle existing monitor. @@ -12352,21 +12766,6 @@ index 00000000000..d83d08e9549 + + addi_d(tmp, tmp, -(int)markWord::monitor_value); // monitor + -+ if (LockingMode == LM_LIGHTWEIGHT) { -+ // If the owner is anonymous, we need to fix it -- in an outline stub. -+ Register tmp2 = disp_hdr; -+ ld_d(tmp2, Address(tmp, ObjectMonitor::owner_offset())); -+ // We cannot use tbnz here, the target might be too far away and cannot -+ // be encoded. -+ assert_different_registers(tmp2, AT); -+ li(AT, (uint64_t)ObjectMonitor::ANONYMOUS_OWNER); -+ andr(AT, tmp2, AT); -+ C2HandleAnonOMOwnerStub* stub = new (Compile::current()->comp_arena()) C2HandleAnonOMOwnerStub(tmp, tmp2); -+ Compile::current()->output()->add_stub(stub); -+ bnez(AT, stub->entry()); -+ bind(stub->continuation()); -+ } -+ + ld_d(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset())); + + Label notRecursive; @@ -12401,6 +12800,258 @@ index 00000000000..d83d08e9549 + bind(no_count); +} + ++void C2_MacroAssembler::fast_lock_lightweight(Register obj, Register flag, Register tmp1, Register tmp2, Register tmp3) { ++ assert(LockingMode == LM_LIGHTWEIGHT, "must be"); ++ assert_different_registers(obj, tmp1, tmp2, tmp3, flag); ++ ++ // Handle inflated monitor. ++ Label inflated; ++ // Finish fast lock successfully. MUST branch to with flag != 0 ++ Label locked; ++ // Finish fast lock unsuccessfully. slow_path MUST branch to with flag == 0 ++ Label slow_path; ++ ++ move(flag, R0); ++ if (DiagnoseSyncOnValueBasedClasses != 0) { ++ load_klass(tmp1, obj); ++ ld_wu(tmp1, Address(tmp1, Klass::access_flags_offset())); ++ test_bit(tmp1, tmp1, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS)); ++ bnez(tmp1, slow_path); ++ } ++ ++ const Register tmp1_mark = tmp1; ++ ++ { // Lightweight locking ++ ++ // Push lock to the lock stack and finish successfully. MUST branch to with flag != 0 ++ Label push; ++ ++ const Register tmp2_top = tmp2; ++ const Register tmp3_t = tmp3; ++ ++ // Check if lock-stack is full. ++ ld_wu(tmp2_top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ li(tmp3_t, (unsigned)LockStack::end_offset()); ++ bge(tmp2_top, tmp3_t, slow_path); ++ ++ // Check if recursive. ++ add_d(tmp3_t, TREG, tmp2_top); ++ ld_d(tmp3_t, tmp3_t, -oopSize); ++ beq(obj, tmp3_t, push); ++ ++ // Relaxed normal load to check for monitor. Optimization for monitor case. ++ ld_d(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes())); ++ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value)); ++ bnez(tmp3_t, inflated); ++ ++ // Not inflated ++ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea"); ++ ++ // Try to lock. Transition lock-bits 0b01 => 0b00 ++ ori(tmp1_mark, tmp1_mark, markWord::unlocked_value); ++ xori(tmp3_t, tmp1_mark, markWord::unlocked_value); ++ cmpxchg(Address(obj, 0), tmp1_mark, tmp3_t, flag, true, true /* acquire */); ++ beqz(flag, slow_path); ++ ++ bind(push); ++ // After successful lock, push object on lock-stack. ++ stx_d(obj, TREG, tmp2_top); ++ addi_w(tmp2_top, tmp2_top, oopSize); ++ st_w(tmp2_top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ b(locked); ++ } ++ ++ { // Handle inflated monitor. ++ bind(inflated); ++ ++ // mark contains the tagged ObjectMonitor*. ++ const Register tmp1_tagged_monitor = tmp1_mark; ++ const uintptr_t monitor_tag = markWord::monitor_value; ++ const Register tmp2_owner_addr = tmp2; ++ const Register tmp3_owner = tmp3; ++ ++ // Compute owner address. ++ lea(tmp2_owner_addr, Address(tmp1_tagged_monitor, (in_bytes(ObjectMonitor::owner_offset()) - monitor_tag))); ++ ++ move(tmp3_owner, R0); ++ // CAS owner (null => current thread). ++ cmpxchg(Address(tmp2_owner_addr, 0), tmp3_owner, TREG, flag, true, true /* acquire */); ++ bnez(flag, locked); ++ ++ // Check if recursive. ++ bne(tmp3_owner, TREG, slow_path); ++ ++ // Recursive. ++ increment(Address(tmp1_tagged_monitor, in_bytes(ObjectMonitor::recursions_offset()) - monitor_tag), 1); ++ } ++ ++ bind(locked); ++ // Set flag != 0 ++ li(flag, 1); ++ increment(Address(TREG, JavaThread::held_monitor_count_offset()), 1); ++ ++#ifdef ASSERT ++ // Check that locked label is reached with flag != 0. ++ Label flag_correct; ++ bnez(flag, flag_correct); ++ stop("Fast Lock Flag == 0"); ++#endif ++ ++ bind(slow_path); ++#ifdef ASSERT ++ // Check that slow_path label is reached with flag == 0. ++ beqz(flag, flag_correct); ++ stop("Fast Lock Flag != 0"); ++ bind(flag_correct); ++#endif ++ // C2 uses the value of flag (0 vs !0) to determine the continuation. ++} ++ ++void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register flag, Register tmp1, Register tmp2, Register tmp3) { ++ assert(LockingMode == LM_LIGHTWEIGHT, "must be"); ++ assert_different_registers(obj, tmp1, tmp2, tmp3, flag, AT); ++ ++ // Handle inflated monitor. ++ Label inflated, inflated_load_monitor; ++ // Finish fast unlock successfully. unlocked MUST branch to with flag == 0 ++ Label unlocked; ++ // Finish fast unlock unsuccessfully. MUST branch to with flag != 0 ++ Label slow_path; ++ ++ const Register tmp1_mark = tmp1; ++ const Register tmp2_top = tmp2; ++ const Register tmp3_t = tmp3; ++ ++ move(flag, R0); ++ { // Lightweight unlock ++ ++ // Check if obj is top of lock-stack. ++ ld_wu(tmp2_top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ addi_w(tmp2_top, tmp2_top, -oopSize); ++ ldx_d(tmp3_t, TREG, tmp2_top); ++ // Top of lock stack was not obj. Must be monitor. ++ bne(obj, tmp3_t, inflated_load_monitor); ++ ++ // Pop lock-stack. ++ DEBUG_ONLY(stx_d(R0, TREG, tmp2_top);) ++ st_w(tmp2_top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ ++ // Check if recursive. ++ add_d(tmp3_t, TREG, tmp2_top); ++ ld_d(tmp3_t, tmp3_t, -oopSize); ++ beq(obj, tmp3_t, unlocked); ++ ++ // Not recursive. ++ // Load Mark. ++ ld_d(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes())); ++ ++ // Check header for monitor (0b10). ++ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value)); ++ bnez(tmp3_t, inflated); ++ ++ // Try to unlock. Transition lock bits 0b00 => 0b01 ++ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); ++ ori(tmp3_t, tmp1_mark, markWord::unlocked_value); ++ cmpxchg(Address(obj, 0), tmp1_mark, tmp3_t, flag, false, false /* acquire */); ++ bnez(flag, unlocked); ++ ++ // Compare and exchange failed. ++ // Restore lock-stack and handle the unlock in runtime. ++ DEBUG_ONLY(stx_d(obj, TREG, tmp2_top);) ++ addi_w(tmp2_top, tmp2_top, oopSize); ++ st_d(tmp2_top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ b(slow_path); ++ } ++ ++ { // Handle inflated monitor. ++ bind(inflated_load_monitor); ++ ld_d(tmp1_mark, Address(obj, oopDesc::mark_offset_in_bytes())); ++#ifdef ASSERT ++ test_bit(tmp3_t, tmp1_mark, exact_log2(markWord::monitor_value)); ++ bnez(tmp3_t, inflated); ++ stop("Fast Unlock not monitor"); ++#endif ++ ++ bind(inflated); ++ ++#ifdef ASSERT ++ Label check_done; ++ addi_w(tmp2_top, tmp2_top, -oopSize); ++ li(tmp3_t, in_bytes(JavaThread::lock_stack_base_offset())); ++ blt(tmp2_top, tmp3_t, check_done); ++ ldx_d(tmp3_t, TREG, tmp2_top); ++ bne(obj, tmp3_t, inflated); ++ stop("Fast Unlock lock on stack"); ++ bind(check_done); ++#endif ++ ++ // mark contains the tagged ObjectMonitor*. ++ const Register tmp1_monitor = tmp1_mark; ++ const intptr_t monitor_tag = markWord::monitor_value; ++ ++ // Untag the monitor. ++ addi_d(tmp1_monitor, tmp1_mark, -monitor_tag); ++ ++ const Register tmp2_recursions = tmp2; ++ Label not_recursive; ++ ++ // Check if recursive. ++ ld_d(tmp2_recursions, Address(tmp1_monitor, ObjectMonitor::recursions_offset())); ++ beqz(tmp2_recursions, not_recursive); ++ ++ // Recursive unlock. ++ addi_d(tmp2_recursions, tmp2_recursions, -1); ++ st_d(tmp2_recursions, Address(tmp1_monitor, ObjectMonitor::recursions_offset())); ++ b(unlocked); ++ ++ bind(not_recursive); ++ ++ Label release; ++ const Register tmp2_owner_addr = tmp2; ++ ++ // Compute owner address. ++ lea(tmp2_owner_addr, Address(tmp1_monitor, ObjectMonitor::owner_offset())); ++ ++ // Check if the entry lists are empty. ++ ld_d(AT, Address(tmp1_monitor, ObjectMonitor::EntryList_offset())); ++ ld_d(tmp3_t, Address(tmp1_monitor, ObjectMonitor::cxq_offset())); ++ orr(AT, AT, tmp3_t); ++ beqz(AT, release); ++ ++ // The owner may be anonymous and we removed the last obj entry in ++ // the lock-stack. This loses the information about the owner. ++ // Write the thread to the owner field so the runtime knows the owner. ++ st_d(TREG, Address(tmp2_owner_addr, 0)); ++ b(slow_path); ++ ++ bind(release); ++ // Set owner to null. ++ membar(Assembler::Membar_mask_bits(MacroAssembler::LoadStore | MacroAssembler::StoreStore)); ++ st_d(R0, Address(tmp2_owner_addr)); ++ } ++ ++ bind(unlocked); ++ // Set flag != 0 ++ li(flag, 1); ++ decrement(Address(TREG, JavaThread::held_monitor_count_offset()), 1); ++ ++#ifdef ASSERT ++ // Check that unlocked label is reached with flag != 0. ++ Label flag_correct; ++ bnez(flag, flag_correct); ++ stop("Fast Unlock Flag == 0"); ++#endif ++ ++ bind(slow_path); ++#ifdef ASSERT ++ // Check that slow_path label is reached with flag == 0. ++ beqz(flag, flag_correct); ++ stop("Fast Unlock Flag != 0"); ++ bind(flag_correct); ++#endif ++ // C2 uses the value of flag (0 vs !0) to determine the continuation. ++} ++ +typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr); + +void C2_MacroAssembler::string_indexof(Register haystack, Register needle, @@ -13064,213 +13715,125 @@ index 00000000000..d83d08e9549 +} + +// Compare strings, used for char[] and byte[]. -+void C2_MacroAssembler::string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, -+ int ae, Register tmp1, Register tmp2, -+ FloatRegister vtmp1, FloatRegister vtmp2) { -+ Label L, Loop, LoopEnd, HaveResult, Done, Loop_Start, -+ V_L, V_Loop, V_Result, V_Start; -+ -+ bool isLL = ae == StrIntrinsicNode::LL; -+ bool isLU = ae == StrIntrinsicNode::LU; -+ bool isUL = ae == StrIntrinsicNode::UL; -+ bool isUU = ae == StrIntrinsicNode::UU; -+ -+ bool str1_isL = isLL || isLU; -+ bool str2_isL = isLL || isUL; -+ -+ int charsInWord = isLL ? wordSize : wordSize/2; -+ int charsInFloatRegister = (UseLASX && (isLL||isUU))?(isLL? 32 : 16):(isLL? 16 : 8); -+ -+ if (!str1_isL) srli_w(cnt1, cnt1, 1); -+ if (!str2_isL) srli_w(cnt2, cnt2, 1); ++void C2_MacroAssembler::string_compareL(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, ++ FloatRegister vtmp2) { ++ Label L, Loop, LoopEnd, HaveResult, Done, XV_Start, V_Start; + + // compute the difference of lengths (in result) -+ sub_d(result, cnt1, cnt2); // result holds the difference of two lengths ++ sub_d(result, cnt1, cnt2); + + // compute the shorter length (in cnt1) -+ bge(cnt2, cnt1, V_Start); ++ bge(cnt2, cnt1, XV_Start); + move(cnt1, cnt2); ++ bind(XV_Start); ++ ++ // tiny string ++ li(AT, wordSize); ++ blt(cnt1, AT, LoopEnd); ++ ++ if (UseLSX) { ++ slli_d(tmp1, AT, 1); // less than 16 ++ blt(cnt1, tmp1, Loop); ++ } + -+ bind(V_Start); + // it is hard to apply the xvilvl to flate 16 bytes into 32 bytes, + // so we employ the LASX only for the LL or UU StrIntrinsicNode. -+ if (UseLASX && (isLL || isUU)) { -+ ori(AT, R0, charsInFloatRegister); -+ addi_d(tmp1, R0, 16); -+ xvinsgr2vr_d(fscratch, R0, 0); ++ if (UseLASX) { ++ Label XV_L, XV_Loop, XV_Result; ++ ++ slli_d(tmp2, tmp1, 1); // less than 32 ++ blt(cnt1, tmp2, V_Start); ++ ++ li(tmp1, 16); ++ xvxor_v(fscratch, fscratch, fscratch); + xvinsgr2vr_d(fscratch, tmp1, 2); ++ ++ bind(XV_Loop); ++ xvld(vtmp1, str1, 0); ++ xvld(vtmp2, str2, 0); ++ xvxor_v(vtmp1, vtmp1, vtmp2); ++ xvseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, XV_L); ++ ++ addi_d(cnt1, cnt1, -32); ++ addi_d(str1, str1, 32); ++ addi_d(str2, str2, 32); ++ bge(cnt1, tmp2, XV_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -32); ++ add_d(str1, str1, cnt1); ++ xvld(vtmp1, str1, 0); ++ add_d(str2, str2, cnt1); ++ xvld(vtmp2, str2, 0); ++ xvxor_v(vtmp1, vtmp1, vtmp2); ++ xvseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(XV_L); ++ xvxor_v(vtmp2, vtmp2, vtmp2); ++ xvabsd_b(vtmp1, vtmp1, vtmp2); ++ xvneg_b(vtmp1, vtmp1); ++ xvfrstp_b(vtmp2, vtmp1, fscratch); ++ xvpickve2gr_du(tmp1, vtmp2, 0); ++ addi_d(cnt2, R0, 16); ++ bne(tmp1, cnt2, XV_Result); ++ ++ xvpickve2gr_du(tmp1, vtmp2, 2); ++ addi_d(tmp1, tmp1, 16); ++ ++ // the index value was stored in tmp1 ++ bind(XV_Result); ++ ldx_bu(result, str1, tmp1); ++ ldx_bu(tmp2, str2, tmp1); ++ sub_d(result, result, tmp2); ++ b(Done); ++ } ++ ++ bind(V_Start); ++ if (UseLSX) { ++ Label V_L, V_Loop, V_Result; ++ + bind(V_Loop); -+ blt(cnt1, AT, Loop_Start); -+ if (isLL) { -+ xvld(vtmp1, str1, 0); -+ xvld(vtmp2, str2, 0); -+ xvxor_v(vtmp1, vtmp1, vtmp2); -+ xvseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 32); -+ addi_d(str2, str2, 32); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ xvxor_v(vtmp2, vtmp2, vtmp2); -+ xvabsd_b(vtmp1, vtmp1, vtmp2); -+ xvneg_b(vtmp1, vtmp1); -+ xvfrstp_b(vtmp2, vtmp1, fscratch); -+ xvpickve2gr_du(tmp1, vtmp2, 0); -+ addi_d(cnt2, R0, 16); -+ bne(tmp1, cnt2, V_Result); -+ -+ xvpickve2gr_du(tmp1, vtmp2, 2); -+ addi_d(tmp1, tmp1, 16); -+ -+ // the index value was stored in tmp1 -+ bind(V_Result); -+ ldx_bu(result, str1, tmp1); -+ ldx_bu(tmp2, str2, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } else if (isUU) { -+ xvld(vtmp1, str1, 0); -+ xvld(vtmp2, str2, 0); -+ xvxor_v(vtmp1, vtmp1, vtmp2); -+ xvseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 32); -+ addi_d(str2, str2, 32); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ xvxor_v(vtmp2, vtmp2, vtmp2); -+ xvabsd_h(vtmp1, vtmp1, vtmp2); -+ xvneg_h(vtmp1, vtmp1); -+ xvfrstp_h(vtmp2, vtmp1, fscratch); -+ xvpickve2gr_du(tmp1, vtmp2, 0); -+ addi_d(cnt2, R0, 8); -+ bne(tmp1, cnt2, V_Result); -+ -+ xvpickve2gr_du(tmp1, vtmp2, 2); -+ addi_d(tmp1, tmp1, 8); -+ -+ // the index value was stored in tmp1 -+ bind(V_Result); -+ slli_d(tmp1, tmp1, 1); -+ ldx_hu(result, str1, tmp1); -+ ldx_hu(tmp2, str2, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } -+ } else if (UseLSX) { -+ ori(AT, R0, charsInFloatRegister); -+ vxor_v(fscratch, fscratch, fscratch); -+ bind(V_Loop); -+ blt(cnt1, AT, Loop_Start); -+ if (isLL) { -+ vld(vtmp1, str1, 0); -+ vld(vtmp2, str2, 0); -+ vxor_v(vtmp1, vtmp1, vtmp2); -+ vseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 16); -+ addi_d(str2, str2, 16); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ vxor_v(vtmp2, vtmp2, vtmp2); -+ vabsd_b(vtmp1, vtmp1, vtmp2); -+ vneg_b(vtmp1, vtmp1); -+ vfrstpi_b(vtmp2, vtmp1, 0); -+ vpickve2gr_bu(tmp1, vtmp2, 0); -+ -+ // the index value was stored in tmp1 -+ ldx_bu(result, str1, tmp1); -+ ldx_bu(tmp2, str2, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } else if (isLU) { -+ vld(vtmp1, str1, 0); -+ vld(vtmp2, str2, 0); -+ vilvl_b(vtmp1, fscratch, vtmp1); -+ vxor_v(vtmp1, vtmp1, vtmp2); -+ vseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 8); -+ addi_d(str2, str2, 16); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ vxor_v(vtmp2, vtmp2, vtmp2); -+ vabsd_h(vtmp1, vtmp1, vtmp2); -+ vneg_h(vtmp1, vtmp1); -+ vfrstpi_h(vtmp2, vtmp1, 0); -+ vpickve2gr_bu(tmp1, vtmp2, 0); -+ -+ // the index value was stored in tmp1 -+ ldx_bu(result, str1, tmp1); -+ slli_d(tmp1, tmp1, 1); -+ ldx_hu(tmp2, str2, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } else if (isUL) { -+ vld(vtmp1, str1, 0); -+ vld(vtmp2, str2, 0); -+ vilvl_b(vtmp2, fscratch, vtmp2); -+ vxor_v(vtmp1, vtmp1, vtmp2); -+ vseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 16); -+ addi_d(str2, str2, 8); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ vxor_v(vtmp2, vtmp2, vtmp2); -+ vabsd_h(vtmp1, vtmp1, vtmp2); -+ vneg_h(vtmp1, vtmp1); -+ vfrstpi_h(vtmp2, vtmp1, 0); -+ vpickve2gr_bu(tmp1, vtmp2, 0); -+ -+ // the index value was stored in tmp1 -+ ldx_bu(tmp2, str2, tmp1); -+ slli_d(tmp1, tmp1, 1); -+ ldx_hu(result, str1, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } else if (isUU) { -+ vld(vtmp1, str1, 0); -+ vld(vtmp2, str2, 0); -+ vxor_v(vtmp1, vtmp1, vtmp2); -+ vseteqz_v(FCC0, vtmp1); -+ bceqz(FCC0, V_L); -+ -+ addi_d(str1, str1, 16); -+ addi_d(str2, str2, 16); -+ addi_d(cnt1, cnt1, -charsInFloatRegister); -+ b(V_Loop); -+ -+ bind(V_L); -+ vxor_v(vtmp2, vtmp2, vtmp2); -+ vabsd_h(vtmp1, vtmp1, vtmp2); -+ vneg_h(vtmp1, vtmp1); -+ vfrstpi_h(vtmp2, vtmp1, 0); -+ vpickve2gr_bu(tmp1, vtmp2, 0); -+ -+ // the index value was stored in tmp1 -+ slli_d(tmp1, tmp1, 1); -+ ldx_hu(result, str1, tmp1); -+ ldx_hu(tmp2, str2, tmp1); -+ sub_d(result, result, tmp2); -+ b(Done); -+ } ++ vld(vtmp1, str1, 0); ++ vld(vtmp2, str2, 0); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, V_L); ++ ++ addi_d(cnt1, cnt1, -16); ++ addi_d(str1, str1, 16); ++ addi_d(str2, str2, 16); ++ bge(cnt1, tmp1, V_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -16); ++ add_d(str1, str1, cnt1); ++ vld(vtmp1, str1, 0); ++ add_d(str2, str2, cnt1); ++ vld(vtmp2, str2, 0); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(V_L); ++ vxor_v(vtmp2, vtmp2, vtmp2); ++ vabsd_b(vtmp1, vtmp1, vtmp2); ++ vneg_b(vtmp1, vtmp1); ++ vfrstpi_b(vtmp2, vtmp1, 0); ++ vpickve2gr_bu(tmp1, vtmp2, 0); ++ ++ // the index value was stored in tmp1 ++ ldx_bu(result, str1, tmp1); ++ ldx_bu(tmp2, str2, tmp1); ++ sub_d(result, result, tmp2); ++ b(Done); + } + + // Now the shorter length is in cnt1 and cnt2 can be used as a tmp register @@ -13287,118 +13850,424 @@ index 00000000000..d83d08e9549 + // Fetch 0 to 7 bits of tmp1 and tmp2, subtract to get the result. + // Other types are similar to isLL. + -+ bind(Loop_Start); -+ ori(AT, R0, charsInWord); + bind(Loop); ++ ld_d(tmp1, str1, 0); ++ ld_d(tmp2, str2, 0); ++ beq(tmp1, tmp2, L); ++ xorr(cnt2, tmp1, tmp2); ++ ctz_d(cnt2, cnt2); ++ andi(cnt2, cnt2, 0x38); ++ srl_d(tmp1, tmp1, cnt2); ++ srl_d(tmp2, tmp2, cnt2); ++ bstrpick_d(tmp1, tmp1, 7, 0); ++ bstrpick_d(tmp2, tmp2, 7, 0); ++ sub_d(result, tmp1, tmp2); ++ b(Done); ++ ++ bind(L); ++ addi_d(cnt1, cnt1, -8); ++ addi_d(str1, str1, 8); ++ addi_d(str2, str2, 8); ++ bge(cnt1, AT, Loop); ++ ++ // compare current character ++ bind(LoopEnd); ++ beqz(cnt1, Done); ++ ld_bu(tmp1, str1, 0); ++ ld_bu(tmp2, str2, 0); ++ bne(tmp1, tmp2, HaveResult); ++ addi_d(cnt1, cnt1, -1); ++ addi_d(str1, str1, 1); ++ addi_d(str2, str2, 1); ++ b(LoopEnd); ++ ++ bind(HaveResult); ++ sub_d(result, tmp1, tmp2); ++ ++ bind(Done); ++} ++ ++void C2_MacroAssembler::string_compareU(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, ++ FloatRegister vtmp2) { ++ Label L, Loop, LoopEnd, HaveResult, Done, XV_Start, V_Start; ++ ++ // compute the difference of lengths (in result) ++ srai_w(cnt1, cnt1, 1); ++ srai_w(cnt2, cnt2, 1); ++ sub_d(result, cnt1, cnt2); ++ ++ // compute the shorter length (in cnt1) ++ bge(cnt2, cnt1, XV_Start); ++ move(cnt1, cnt2); ++ bind(XV_Start); ++ ++ // tiny string ++ li(AT, wordSize/2); + blt(cnt1, AT, LoopEnd); -+ if (isLL) { -+ ld_d(tmp1, str1, 0); -+ ld_d(tmp2, str2, 0); -+ beq(tmp1, tmp2, L); -+ xorr(cnt2, tmp1, tmp2); -+ ctz_d(cnt2, cnt2); -+ andi(cnt2, cnt2, 0x38); -+ srl_d(tmp1, tmp1, cnt2); -+ srl_d(tmp2, tmp2, cnt2); -+ bstrpick_d(tmp1, tmp1, 7, 0); -+ bstrpick_d(tmp2, tmp2, 7, 0); -+ sub_d(result, tmp1, tmp2); -+ b(Done); -+ bind(L); -+ addi_d(str1, str1, 8); -+ addi_d(str2, str2, 8); -+ addi_d(cnt1, cnt1, -charsInWord); -+ b(Loop); -+ } else if (isLU) { -+ ld_wu(cnt2, str1, 0); -+ andr(tmp1, R0, R0); -+ bstrins_d(tmp1, cnt2, 7, 0); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp1, cnt2, 23, 16); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp1, cnt2, 39, 32); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp1, cnt2, 55, 48); -+ ld_d(tmp2, str2, 0); -+ beq(tmp1, tmp2, L); -+ xorr(cnt2, tmp1, tmp2); -+ ctz_d(cnt2, cnt2); -+ andi(cnt2, cnt2, 0x30); -+ srl_d(tmp1, tmp1, cnt2); -+ srl_d(tmp2, tmp2, cnt2); -+ bstrpick_d(tmp1, tmp1, 15, 0); -+ bstrpick_d(tmp2, tmp2, 15, 0); -+ sub_d(result, tmp1, tmp2); ++ ++ if (UseLSX) { ++ slli_d(tmp1, AT, 1); // less than 8 ++ blt(cnt1, tmp1, Loop); ++ } ++ ++ // it is hard to apply the xvilvl to flate 16 bytes into 32 bytes, ++ // so we employ the LASX only for the LL or UU StrIntrinsicNode. ++ if (UseLASX) { ++ Label XV_L, XV_Loop, XV_Result; ++ ++ slli_d(tmp2, tmp1, 1); // less than 16 ++ blt(cnt1, tmp2, V_Start); ++ ++ li(tmp1, 16); ++ xvxor_v(fscratch, fscratch, fscratch); ++ xvinsgr2vr_d(fscratch, tmp1, 2); ++ ++ bind(XV_Loop); ++ xvld(vtmp1, str1, 0); ++ xvld(vtmp2, str2, 0); ++ xvxor_v(vtmp1, vtmp1, vtmp2); ++ xvseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, XV_L); ++ ++ addi_d(cnt1, cnt1, -16); ++ addi_d(str1, str1, 32); ++ addi_d(str2, str2, 32); ++ bge(cnt1, tmp2, XV_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -16); ++ alsl_d(str1, cnt1, str1, 0); ++ xvld(vtmp1, str1, 0); ++ alsl_d(str2, cnt1, str2, 0); ++ xvld(vtmp2, str2, 0); ++ xvxor_v(vtmp1, vtmp1, vtmp2); ++ xvseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(XV_L); ++ xvxor_v(vtmp2, vtmp2, vtmp2); ++ xvabsd_h(vtmp1, vtmp1, vtmp2); ++ xvneg_h(vtmp1, vtmp1); ++ xvfrstp_h(vtmp2, vtmp1, fscratch); ++ xvpickve2gr_du(tmp1, vtmp2, 0); ++ addi_d(cnt2, R0, 8); ++ bne(tmp1, cnt2, XV_Result); ++ ++ xvpickve2gr_du(tmp1, vtmp2, 2); ++ addi_d(tmp1, tmp1, 8); ++ ++ // the index value was stored in tmp1 ++ bind(XV_Result); ++ slli_d(tmp1, tmp1, 1); ++ ldx_hu(result, str1, tmp1); ++ ldx_hu(tmp2, str2, tmp1); ++ sub_d(result, result, tmp2); + b(Done); -+ bind(L); -+ addi_d(str1, str1, 4); -+ addi_d(str2, str2, 8); -+ addi_d(cnt1, cnt1, -charsInWord); -+ b(Loop); -+ } else if (isUL) { -+ ld_wu(cnt2, str2, 0); -+ andr(tmp2, R0, R0); -+ bstrins_d(tmp2, cnt2, 7, 0); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp2, cnt2, 23, 16); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp2, cnt2, 39, 32); -+ srli_d(cnt2, cnt2, 8); -+ bstrins_d(tmp2, cnt2, 55, 48); -+ ld_d(tmp1, str1, 0); -+ beq(tmp1, tmp2, L); -+ xorr(cnt2, tmp1, tmp2); -+ ctz_d(cnt2, cnt2); -+ andi(cnt2, cnt2, 0x30); -+ srl_d(tmp1, tmp1, cnt2); -+ srl_d(tmp2, tmp2, cnt2); -+ bstrpick_d(tmp1, tmp1, 15, 0); -+ bstrpick_d(tmp2, tmp2, 15, 0); -+ sub_d(result, tmp1, tmp2); ++ } ++ ++ bind(V_Start); ++ if (UseLSX) { ++ Label V_L, V_Loop, V_Result; ++ ++ bind(V_Loop); ++ vld(vtmp1, str1, 0); ++ vld(vtmp2, str2, 0); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, V_L); ++ ++ addi_d(cnt1, cnt1, -8); ++ addi_d(str1, str1, 16); ++ addi_d(str2, str2, 16); ++ bge(cnt1, tmp1, V_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -8); ++ alsl_d(str1, cnt1, str1, 0); ++ vld(vtmp1, str1, 0); ++ alsl_d(str2, cnt1, str2, 0); ++ vld(vtmp2, str2, 0); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(V_L); ++ vxor_v(vtmp2, vtmp2, vtmp2); ++ vabsd_h(vtmp1, vtmp1, vtmp2); ++ vneg_h(vtmp1, vtmp1); ++ vfrstpi_h(vtmp2, vtmp1, 0); ++ vpickve2gr_bu(tmp1, vtmp2, 0); ++ ++ // the index value was stored in tmp1 ++ slli_d(tmp1, tmp1, 1); ++ ldx_hu(result, str1, tmp1); ++ ldx_hu(tmp2, str2, tmp1); ++ sub_d(result, result, tmp2); + b(Done); -+ bind(L); ++ } ++ ++ bind(Loop); ++ ld_d(tmp1, str1, 0); ++ ld_d(tmp2, str2, 0); ++ beq(tmp1, tmp2, L); ++ xorr(cnt2, tmp1, tmp2); ++ ctz_d(cnt2, cnt2); ++ andi(cnt2, cnt2, 0x30); ++ srl_d(tmp1, tmp1, cnt2); ++ srl_d(tmp2, tmp2, cnt2); ++ bstrpick_d(tmp1, tmp1, 15, 0); ++ bstrpick_d(tmp2, tmp2, 15, 0); ++ sub_d(result, tmp1, tmp2); ++ b(Done); ++ ++ bind(L); ++ addi_d(cnt1, cnt1, -4); ++ addi_d(str1, str1, 8); ++ addi_d(str2, str2, 8); ++ bge(cnt1, AT, Loop); ++ ++ // compare current character ++ bind(LoopEnd); ++ beqz(cnt1, Done); ++ ld_hu(tmp1, str1, 0); ++ ld_hu(tmp2, str2, 0); ++ bne(tmp1, tmp2, HaveResult); ++ addi_d(cnt1, cnt1, -1); ++ addi_d(str1, str1, 2); ++ addi_d(str2, str2, 2); ++ b(LoopEnd); ++ ++ bind(HaveResult); ++ sub_d(result, tmp1, tmp2); ++ ++ bind(Done); ++} ++ ++void C2_MacroAssembler::string_compareLU(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, ++ FloatRegister vtmp2) { ++ Label L, Loop, LoopEnd, HaveResult, Done, V_Start; ++ ++ ++ // compute the difference of lengths (in result) ++ srai_w(cnt2, cnt2, 1); ++ sub_d(result, cnt1, cnt2); ++ ++ // compute the shorter length (in cnt1) ++ bge(cnt2, cnt1, V_Start); ++ move(cnt1, cnt2); ++ bind(V_Start); ++ ++ // tiny string ++ li(AT, wordSize/2); ++ blt(cnt1, AT, LoopEnd); ++ ++ if (UseLSX) { ++ slli_d(tmp1, AT, 1); // less than 8 ++ blt(cnt1, tmp1, Loop); ++ ++ Label V_L, V_Loop, V_Result; ++ ++ vxor_v(fscratch, fscratch, fscratch); ++ ++ bind(V_Loop); ++ vld(vtmp1, str1, 0); ++ vld(vtmp2, str2, 0); ++ vilvl_b(vtmp1, fscratch, vtmp1); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, V_L); ++ ++ addi_d(cnt1, cnt1, -8); + addi_d(str1, str1, 8); -+ addi_d(str2, str2, 4); -+ addi_d(cnt1, cnt1, -charsInWord); -+ b(Loop); -+ } else { // isUU -+ ld_d(tmp1, str1, 0); -+ ld_d(tmp2, str2, 0); -+ beq(tmp1, tmp2, L); -+ xorr(cnt2, tmp1, tmp2); -+ ctz_d(cnt2, cnt2); -+ andi(cnt2, cnt2, 0x30); -+ srl_d(tmp1, tmp1, cnt2); -+ srl_d(tmp2, tmp2, cnt2); -+ bstrpick_d(tmp1, tmp1, 15, 0); -+ bstrpick_d(tmp2, tmp2, 15, 0); -+ sub_d(result, tmp1, tmp2); ++ addi_d(str2, str2, 16); ++ bge(cnt1, tmp1, V_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -8); ++ add_d(str1, str1, cnt1); ++ vld(vtmp1, str1, 0); ++ alsl_d(str2, cnt1, str2, 0); ++ vld(vtmp2, str2, 0); ++ vilvl_b(vtmp1, fscratch, vtmp1); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(V_L); ++ vxor_v(vtmp2, vtmp2, vtmp2); ++ vabsd_h(vtmp1, vtmp1, vtmp2); ++ vneg_h(vtmp1, vtmp1); ++ vfrstpi_h(vtmp2, vtmp1, 0); ++ vpickve2gr_bu(tmp1, vtmp2, 0); ++ ++ // the index value was stored in tmp1 ++ ldx_bu(result, str1, tmp1); ++ slli_d(tmp1, tmp1, 1); ++ ldx_hu(tmp2, str2, tmp1); ++ sub_d(result, result, tmp2); + b(Done); -+ bind(L); -+ addi_d(str1, str1, 8); -+ addi_d(str2, str2, 8); -+ addi_d(cnt1, cnt1, -charsInWord); -+ b(Loop); + } + ++ bind(Loop); ++ ld_wu(cnt2, str1, 0); ++ andr(tmp1, R0, R0); ++ bstrins_d(tmp1, cnt2, 7, 0); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp1, cnt2, 23, 16); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp1, cnt2, 39, 32); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp1, cnt2, 55, 48); ++ ld_d(tmp2, str2, 0); ++ beq(tmp1, tmp2, L); ++ xorr(cnt2, tmp1, tmp2); ++ ctz_d(cnt2, cnt2); ++ andi(cnt2, cnt2, 0x30); ++ srl_d(tmp1, tmp1, cnt2); ++ srl_d(tmp2, tmp2, cnt2); ++ bstrpick_d(tmp1, tmp1, 15, 0); ++ bstrpick_d(tmp2, tmp2, 15, 0); ++ sub_d(result, tmp1, tmp2); ++ b(Done); ++ bind(L); ++ addi_d(cnt1, cnt1, -4); ++ addi_d(str1, str1, 4); ++ addi_d(str2, str2, 8); ++ bge(cnt1, AT, Loop); ++ ++ // compare current character + bind(LoopEnd); + beqz(cnt1, Done); -+ if (str1_isL) { -+ ld_bu(tmp1, str1, 0); -+ } else { -+ ld_hu(tmp1, str1, 0); ++ ld_bu(tmp1, str1, 0); ++ ld_hu(tmp2, str2, 0); ++ bne(tmp1, tmp2, HaveResult); ++ addi_d(cnt1, cnt1, -1); ++ addi_d(str1, str1, 1); ++ addi_d(str2, str2, 2); ++ b(LoopEnd); ++ ++ bind(HaveResult); ++ sub_d(result, tmp1, tmp2); ++ ++ bind(Done); ++} ++ ++void C2_MacroAssembler::string_compareUL(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, ++ FloatRegister vtmp2) { ++ Label L, Loop, LoopEnd, HaveResult, Done, V_Start; ++ ++ // compute the difference of lengths (in result) ++ srai_w(cnt1, cnt1, 1); ++ sub_d(result, cnt1, cnt2); ++ ++ // compute the shorter length (in cnt1) ++ bge(cnt2, cnt1, V_Start); ++ move(cnt1, cnt2); ++ bind(V_Start); ++ ++ // tiny string ++ li(AT, wordSize/2); ++ blt(cnt1, AT, LoopEnd); ++ ++ if (UseLSX) { ++ slli_d(tmp1, AT, 1); // less than 8 ++ blt(cnt1, tmp1, Loop); ++ ++ Label V_L, V_Loop, V_Result; ++ ++ vxor_v(fscratch, fscratch, fscratch); ++ ++ bind(V_Loop); ++ vld(vtmp2, str2, 0); ++ vld(vtmp1, str1, 0); ++ vilvl_b(vtmp2, fscratch, vtmp2); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bceqz(FCC0, V_L); ++ ++ addi_d(cnt1, cnt1, -8); ++ addi_d(str1, str1, 16); ++ addi_d(str2, str2, 8); ++ bge(cnt1, tmp1, V_Loop); ++ ++ // deal with the last loop ++ beqz(cnt1, Done); ++ addi_d(cnt1, cnt1, -8); ++ add_d(str2, str2, cnt1); ++ vld(vtmp2, str2, 0); ++ alsl_d(str1, cnt1, str1, 0); ++ vld(vtmp1, str1, 0); ++ vilvl_b(vtmp2, fscratch, vtmp2); ++ vxor_v(vtmp1, vtmp1, vtmp2); ++ vseteqz_v(FCC0, vtmp1); ++ bcnez(FCC0, Done); ++ ++ bind(V_L); ++ vxor_v(vtmp2, vtmp2, vtmp2); ++ vabsd_h(vtmp1, vtmp1, vtmp2); ++ vneg_h(vtmp1, vtmp1); ++ vfrstpi_h(vtmp2, vtmp1, 0); ++ vpickve2gr_bu(tmp1, vtmp2, 0); ++ ++ // the index value was stored in tmp1 ++ ldx_bu(tmp2, str2, tmp1); ++ slli_d(tmp1, tmp1, 1); ++ ldx_hu(result, str1, tmp1); ++ sub_d(result, result, tmp2); ++ b(Done); + } + ++ bind(Loop); ++ ld_wu(cnt2, str2, 0); ++ andr(tmp2, R0, R0); ++ bstrins_d(tmp2, cnt2, 7, 0); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp2, cnt2, 23, 16); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp2, cnt2, 39, 32); ++ srli_d(cnt2, cnt2, 8); ++ bstrins_d(tmp2, cnt2, 55, 48); ++ ld_d(tmp1, str1, 0); ++ beq(tmp1, tmp2, L); ++ xorr(cnt2, tmp1, tmp2); ++ ctz_d(cnt2, cnt2); ++ andi(cnt2, cnt2, 0x30); ++ srl_d(tmp1, tmp1, cnt2); ++ srl_d(tmp2, tmp2, cnt2); ++ bstrpick_d(tmp1, tmp1, 15, 0); ++ bstrpick_d(tmp2, tmp2, 15, 0); ++ sub_d(result, tmp1, tmp2); ++ b(Done); ++ bind(L); ++ addi_d(cnt1, cnt1, -4); ++ addi_d(str1, str1, 8); ++ addi_d(str2, str2, 4); ++ bge(cnt1, AT, Loop); ++ + // compare current character -+ if (str2_isL) { -+ ld_bu(tmp2, str2, 0); -+ } else { -+ ld_hu(tmp2, str2, 0); -+ } ++ bind(LoopEnd); ++ beqz(cnt1, Done); ++ ld_hu(tmp1, str1, 0); ++ ld_bu(tmp2, str2, 0); + bne(tmp1, tmp2, HaveResult); -+ addi_d(str1, str1, str1_isL ? 1 : 2); -+ addi_d(str2, str2, str2_isL ? 1 : 2); + addi_d(cnt1, cnt1, -1); ++ addi_d(str1, str1, 2); ++ addi_d(str2, str2, 1); + b(LoopEnd); + + bind(HaveResult); @@ -14074,15 +14943,122 @@ index 00000000000..d83d08e9549 + } + return MacroAssembler::in_scratch_emit_size(); +} ++ ++// jdk.internal.util.ArraysSupport.vectorizedHashCode ++void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register result, ++ Register tmp1, Register tmp2, Register tmp3, ++ Register tmp4, Register tmp5, Register tmp6, ++ Register tmp7, BasicType eltype) ++{ ++ assert_different_registers(ary, cnt, result, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, SCR1); ++ ++ const int elsize = arrays_hashcode_elsize(eltype); ++ const int chunks_end_shift = exact_log2(elsize); ++ ++ switch (eltype) { ++ case T_BOOLEAN: BLOCK_COMMENT("arrays_hashcode(unsigned byte) {"); break; ++ case T_CHAR: BLOCK_COMMENT("arrays_hashcode(char) {"); break; ++ case T_BYTE: BLOCK_COMMENT("arrays_hashcode(byte) {"); break; ++ case T_SHORT: BLOCK_COMMENT("arrays_hashcode(short) {"); break; ++ case T_INT: BLOCK_COMMENT("arrays_hashcode(int) {"); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ ++ const int stride = 4; ++ const Register pow31_4 = tmp1; ++ const Register pow31_3 = tmp2; ++ const Register pow31_2 = tmp3; ++ const Register chunks = tmp4; ++ const Register chunks_end = chunks; ++ ++ Label DONE, TAIL, TAIL_LOOP, WIDE_LOOP; ++ ++ // result has a value initially ++ ++ beqz(cnt, DONE); ++ ++ srli_d(chunks, cnt, stride>>1); ++ slli_d(chunks, chunks, stride>>1); ++ beqz(chunks, TAIL); ++ ++ li(pow31_4, 923521); // [31^^4] ++ li(pow31_3, 29791); // [31^^3] ++ li(pow31_2, 961); // [31^^2] ++ ++ slli_d(chunks_end, chunks, chunks_end_shift); ++ add_d(chunks_end, ary, chunks_end); ++ andi(cnt, cnt, stride-1); // don't forget about tail! ++ ++ bind(WIDE_LOOP); ++ mul_w(result, result, pow31_4); // 31^^4 * h ++ arrays_hashcode_elload(SCR1, Address(ary, 0 * elsize), eltype); ++ arrays_hashcode_elload(tmp7, Address(ary, 1 * elsize), eltype); ++ arrays_hashcode_elload(tmp5, Address(ary, 2 * elsize), eltype); ++ arrays_hashcode_elload(tmp6, Address(ary, 3 * elsize), eltype); ++ mul_w(SCR1, SCR1, pow31_3); // 31^^3 * ary[i+0] ++ add_w(result, result, SCR1); ++ mul_w(tmp7, tmp7, pow31_2); // 31^^2 * ary[i+1] ++ add_w(result, result, tmp7); ++ slli_w(SCR1, tmp5, 5); // optimize 31^^1 * ary[i+2] ++ sub_w(tmp5, SCR1, tmp5); // with ary[i+2]<<5 - ary[i+2] ++ add_w(result, result, tmp5); ++ add_w(result, result, tmp6); // 31^^4 * h + 31^^3 * ary[i+0] + 31^^2 * ary[i+1] ++ // + 31^^1 * ary[i+2] + 31^^0 * ary[i+3] ++ addi_d(ary, ary, elsize * stride); ++ bne(ary, chunks_end, WIDE_LOOP); ++ beqz(cnt, DONE); ++ ++ bind(TAIL); ++ slli_d(chunks_end, cnt, chunks_end_shift); ++ add_d(chunks_end, ary, chunks_end); ++ ++ bind(TAIL_LOOP); ++ arrays_hashcode_elload(SCR1, Address(ary), eltype); ++ slli_w(tmp7, result, 5); // optimize 31 * result ++ sub_w(result, tmp7, result); // with result<<5 - result ++ add_w(result, result, SCR1); ++ addi_d(ary, ary, elsize); ++ bne(ary, chunks_end, TAIL_LOOP); ++ ++ bind(DONE); ++ BLOCK_COMMENT("} // arrays_hashcode"); ++} ++ ++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; ++ } ++} ++ ++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: ld_bu(dst, src); break; ++ case T_BYTE: ld_b(dst, src); break; ++ case T_SHORT: ld_h(dst, src); break; ++ case T_CHAR: ld_hu(dst, src); break; ++ case T_INT: ld_w(dst, src); break; ++ default: ++ ShouldNotReachHere(); ++ } ++} diff --git a/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.hpp new file mode 100644 -index 00000000000..804e060f195 +index 00000000000..8e4f0150897 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.hpp -@@ -0,0 +1,141 @@ +@@ -0,0 +1,171 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -14119,12 +15095,33 @@ index 00000000000..804e060f195 + Register disp_hdr, Register tmp); + void fast_unlock_c2(Register oop, Register box, Register flag, + Register disp_hdr, Register tmp); ++ // Code used by cmpFastLockLightweight and cmpFastUnlockLightweight mach instructions in .ad file. ++ void fast_lock_lightweight(Register object, Register flag, ++ Register tmp1, Register tmp2, Register tmp3); ++ void fast_unlock_lightweight(Register object, Register flag, ++ Register tmp1, Register tmp2, Register tmp3); + + // Compare strings. -+ void string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, -+ int ae, Register tmp1, Register tmp2, -+ FloatRegister vtmp1, FloatRegister vtmp2); ++ void string_compareL(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, FloatRegister vtmp2); ++ void string_compareU(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, FloatRegister vtmp2); ++ void string_compareLU(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, FloatRegister vtmp2); ++ void string_compareUL(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register result, ++ Register tmp1, Register tmp2, ++ FloatRegister vtmp1, FloatRegister vtmp2); + + // Find index of char in Latin-1 string + void stringL_indexof_char(Register str1, Register cnt1, @@ -14151,6 +15148,15 @@ index 00000000000..804e060f195 + Register cnt, Register tmp1, Register tmp2, Register result, + bool is_char, bool is_array); + ++ void arrays_hashcode(Register ary, Register cnt, Register result, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ Register tmp5, Register tmp6, ++ Register tmp7, BasicType eltype); ++ // helper function for arrays_hashcode ++ int arrays_hashcode_elsize(BasicType eltype); ++ void arrays_hashcode_elload(Register dst, Address src, BasicType eltype); ++ + // Memory Data Type + #define INT_TYPE 0x100 + #define FLOAT_TYPE 0x200 @@ -14438,13 +15444,13 @@ index 00000000000..c8041a57f96 +#endif // CPU_LOONGARCH_CODEBUFFER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp b/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp new file mode 100644 -index 00000000000..17ee4b75f72 +index 00000000000..31220cbe63f --- /dev/null +++ b/src/hotspot/cpu/loongarch/compiledIC_loongarch.cpp -@@ -0,0 +1,138 @@ +@@ -0,0 +1,127 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -14470,28 +15476,24 @@ index 00000000000..17ee4b75f72 +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" -+#include "code/icBuffer.hpp" +#include "code/nmethod.hpp" ++#include "logging/log.hpp" +#include "memory/resourceArea.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/safepoint.hpp" + +// ---------------------------------------------------------------------------- + -+#define __ _masm. -+address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) { -+ precond(cbuf.stubs()->start() != badAddress); -+ precond(cbuf.stubs()->end() != badAddress); ++#define __ masm-> ++address CompiledDirectCall::emit_to_interp_stub(MacroAssembler *masm, address mark) { ++ precond(__ code()->stubs()->start() != badAddress); ++ precond(__ code()->stubs()->end() != badAddress); + + if (mark == nullptr) { -+ mark = cbuf.insts_mark(); // get mark within main instrs section ++ mark = __ inst_mark(); // get mark within main instrs section. + } + -+ // Note that the code buffer's insts_mark is always relative to insts. -+ // That's why we must use the macroassembler to generate a stub. -+ MacroAssembler _masm(&cbuf); -+ -+ address base = __ start_a_stub(CompiledStaticCall::to_interp_stub_size()); ++ address base = __ start_a_stub(CompiledDirectCall::to_interp_stub_size()); + if (base == nullptr) return nullptr; // CodeBuffer::expand failed + // static stub relocation stores the instruction address of the call + @@ -14507,30 +15509,23 @@ index 00000000000..17ee4b75f72 +} +#undef __ + -+int CompiledStaticCall::to_interp_stub_size() { ++int CompiledDirectCall::to_interp_stub_size() { + return NativeInstruction::nop_instruction_size + NativeMovConstReg::instruction_size + NativeGeneralJump::instruction_size; +} + -+int CompiledStaticCall::to_trampoline_stub_size() { ++int CompiledDirectCall::to_trampoline_stub_size() { + return NativeInstruction::nop_instruction_size + NativeCallTrampolineStub::instruction_size; +} + +// Relocation entries for call stub, compiled java to interpreter. -+int CompiledStaticCall::reloc_to_interp_stub() { ++int CompiledDirectCall::reloc_to_interp_stub() { + return 16; +} + -+void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { ++void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address entry) { + address stub = find_stub(); + guarantee(stub != nullptr, "stub not found"); + -+ if (TraceICs) { -+ ResourceMark rm; -+ tty->print_cr("CompiledDirectStaticCall@" INTPTR_FORMAT ": set_to_interpreted %s", -+ p2i(instruction_address()), -+ callee->name_and_sig_as_C_string()); -+ } -+ + // Creation also verifies the object. + NativeMovConstReg* method_holder = nativeMovConstReg_at(stub + NativeInstruction::nop_instruction_size); + NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); @@ -14544,7 +15539,7 @@ index 00000000000..17ee4b75f72 + set_destination_mt_safe(stub); +} + -+void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { ++void CompiledDirectCall::set_stub_to_clean(static_stub_Relocation* static_stub) { + assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); + // Reset stub. + address stub = static_stub->addr(); @@ -14560,7 +15555,7 @@ index 00000000000..17ee4b75f72 +// Non-product mode code +#ifndef PRODUCT + -+void CompiledDirectStaticCall::verify() { ++void CompiledDirectCall::verify() { + // Verify call. + _call->verify(); + if (os::is_MP()) { @@ -14704,13 +15699,13 @@ index 00000000000..c2d91996000 +#endif // CPU_LOONGARCH_CONTINUATIONENTRY_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/continuationEntry_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/continuationEntry_loongarch.inline.hpp new file mode 100644 -index 00000000000..d1c01ee42f0 +index 00000000000..492964b8bea --- /dev/null +++ b/src/hotspot/cpu/loongarch/continuationEntry_loongarch.inline.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -14746,7 +15741,7 @@ index 00000000000..d1c01ee42f0 +inline frame ContinuationEntry::to_frame() const { + static CodeBlob* cb = CodeCache::find_blob_fast(entry_pc()); + assert(cb != nullptr, ""); -+ assert(cb->as_compiled_method()->method()->is_continuation_enter_intrinsic(), ""); ++ assert(cb->as_nmethod()->method()->is_continuation_enter_intrinsic(), ""); + return frame(entry_sp(), entry_sp(), entry_fp(), entry_pc(), cb); +} + @@ -16092,13 +17087,13 @@ index 00000000000..7e4d0d79e44 +#endif // CPU_LOONGARCH_FOREIGN_GLOBALS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.cpp b/src/hotspot/cpu/loongarch/frame_loongarch.cpp new file mode 100644 -index 00000000000..09703c9d7c4 +index 00000000000..3b9ea71d315 --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.cpp @@ -0,0 +1,631 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -16300,7 +17295,7 @@ index 00000000000..09703c9d7c4 + return false; + } + -+ CompiledMethod* nm = sender_blob->as_compiled_method_or_null(); ++ 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()) { @@ -16312,7 +17307,7 @@ index 00000000000..09703c9d7c4 + // because the return address counts against the callee's frame. + + if (sender_blob->frame_size() <= 0) { -+ assert(!sender_blob->is_compiled(), "should count return address at least"); ++ assert(!sender_blob->is_nmethod(), "should count return address at least"); + return false; + } + @@ -16321,7 +17316,7 @@ index 00000000000..09703c9d7c4 + // should not be anything but the call stub (already covered), the interpreter (already covered) + // or an nmethod. + -+ if (!sender_blob->is_compiled()) { ++ if (!sender_blob->is_nmethod()) { + return false; + } + @@ -16370,7 +17365,7 @@ index 00000000000..09703c9d7c4 + DEBUG_ONLY(address old_pc = _pc;) + *pc_addr = pc; + _pc = pc; // must be set before call to get_deopt_original_pc -+ address original_pc = CompiledMethod::get_deopt_original_pc(this); ++ address original_pc = get_deopt_original_pc(); + if (original_pc != nullptr) { + assert(original_pc == old_pc, "expected original PC to be stored before patching"); + _deopt_state = is_deoptimized; @@ -16489,7 +17484,7 @@ index 00000000000..09703c9d7c4 +// given unextended SP. The unextended SP might also be the saved SP +// for MethodHandle call sites. +#ifdef ASSERT -+void frame::verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp) { ++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 @@ -16512,12 +17507,12 @@ index 00000000000..09703c9d7c4 + // returning to any of these call sites. + + if (_cb != nullptr) { -+ CompiledMethod* sender_cm = _cb->as_compiled_method_or_null(); -+ if (sender_cm != 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_cm->is_deopt_entry(_pc) || -+ sender_cm->is_deopt_mh_entry(_pc)) { -+ verify_deopt_original_pc(sender_cm, _unextended_sp); ++ if (sender_nm->is_deopt_entry(_pc) || ++ sender_nm->is_deopt_mh_entry(_pc)) { ++ verify_deopt_original_pc(sender_nm, _unextended_sp); + } + } + } @@ -16729,13 +17724,13 @@ index 00000000000..09703c9d7c4 +} diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.hpp b/src/hotspot/cpu/loongarch/frame_loongarch.hpp new file mode 100644 -index 00000000000..36dd89ff08f +index 00000000000..65ac398e40e --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.hpp -@@ -0,0 +1,200 @@ +@@ -0,0 +1,198 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -16887,11 +17882,9 @@ index 00000000000..36dd89ff08f + +#ifdef ASSERT + // Used in frame::sender_for_{interpreter,compiled}_frame -+ static void verify_deopt_original_pc(CompiledMethod* nm, intptr_t* unextended_sp); ++ static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp); +#endif + -+ const ImmutableOopMap* get_oop_map() const; -+ + public: + // Constructors + @@ -16935,13 +17928,13 @@ index 00000000000..36dd89ff08f +#endif // CPU_LOONGARCH_FRAME_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp new file mode 100644 -index 00000000000..8eac47d6ef9 +index 00000000000..f5e492f22a2 --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp -@@ -0,0 +1,473 @@ +@@ -0,0 +1,459 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -17007,11 +18000,11 @@ index 00000000000..8eac47d6ef9 +inline void frame::setup(address pc) { + adjust_unextended_sp(); + -+ address original_pc = CompiledMethod::get_deopt_original_pc(this); ++ address original_pc = get_deopt_original_pc(); + if (original_pc != nullptr) { + _pc = original_pc; + _deopt_state = is_deoptimized; -+ assert(_cb == nullptr || _cb->as_compiled_method()->insts_contains_inclusive(_pc), ++ assert(_cb == nullptr || _cb->as_nmethod()->insts_contains_inclusive(_pc), + "original PC must be in the main code section of the compiled method (or must be immediately following it)"); + } else { + if (_cb == SharedRuntime::deopt_blob()) { @@ -17108,7 +18101,7 @@ index 00000000000..8eac47d6ef9 + _cb = CodeCache::find_blob(_pc); + adjust_unextended_sp(); + -+ address original_pc = CompiledMethod::get_deopt_original_pc(this); ++ address original_pc = get_deopt_original_pc(); + if (original_pc != nullptr) { + _pc = original_pc; + _deopt_state = is_deoptimized; @@ -17124,7 +18117,7 @@ index 00000000000..8eac47d6ef9 + unextended_sp() == other.unextended_sp() && + fp() == other.fp() && + pc() == other.pc(); -+ assert(!ret || ret && cb() == other.cb() && _deopt_state == other._deopt_state, "inconsistent construction"); ++ assert(!ret || (cb() == other.cb() && _deopt_state == other._deopt_state), "inconsistent construction"); + return ret; +} + @@ -17169,8 +18162,8 @@ index 00000000000..8eac47d6ef9 +} + +inline int frame::compiled_frame_stack_argsize() const { -+ assert(cb()->is_compiled(), ""); -+ return (cb()->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord; ++ assert(cb()->is_nmethod(), ""); ++ return (cb()->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord; +} + +inline void frame::interpreted_frame_oop_map(InterpreterOopMap* mask) const { @@ -17283,20 +18276,6 @@ index 00000000000..8eac47d6ef9 + return frame::sender_sp_offset - frame::return_addr_offset; +} + -+inline const ImmutableOopMap* frame::get_oop_map() const { -+ if (_cb == nullptr) return nullptr; -+ if (_cb->oop_maps() != nullptr) { -+ NativePostCallNop* nop = nativePostCallNop_at(_pc); -+ if (nop != nullptr && nop->displacement() != 0) { -+ int slot = ((nop->displacement() >> 24) & 0xff); -+ return _cb->oop_map_for_slot(slot, _pc); -+ } -+ const ImmutableOopMap* oop_map = OopMapSet::find_map(this); -+ return oop_map; -+ } -+ return nullptr; -+} -+ +//------------------------------------------------------------------------------ +// frame::sender +frame frame::sender(RegisterMap* map) const { @@ -17365,7 +18344,7 @@ index 00000000000..8eac47d6ef9 + // Tell GC to use argument oopmaps for some runtime stubs that need it. + // For C1, the runtime stub might not have oop maps, so set this flag + // outside of update_register_map. -+ if (!_cb->is_compiled()) { // compiled frames do not use callee-saved registers ++ if (!_cb->is_nmethod()) { // compiled frames do not use callee-saved registers + map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread())); + if (oop_map() != nullptr) { + _oop_map->update_register_map(this, map); @@ -17414,13 +18393,13 @@ index 00000000000..8eac47d6ef9 +#endif // CPU_LOONGARCH_FRAME_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp new file mode 100644 -index 00000000000..fd125f141f4 +index 00000000000..04e50bead07 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/g1/g1BarrierSetAssembler_loongarch.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -17449,8 +18428,8 @@ index 00000000000..fd125f141f4 +#include "gc/g1/g1BarrierSetAssembler.hpp" +#include "gc/g1/g1BarrierSetRuntime.hpp" +#include "gc/g1/g1CardTable.hpp" ++#include "gc/g1/g1HeapRegion.hpp" +#include "gc/g1/g1ThreadLocalData.hpp" -+#include "gc/g1/heapRegion.hpp" +#include "interpreter/interp_masm.hpp" +#include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" @@ -17650,7 +18629,7 @@ index 00000000000..fd125f141f4 + + // Does store cross heap regions? + __ xorr(tmp1, store_addr, new_val); -+ __ srli_d(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes); ++ __ srli_d(tmp1, tmp1, G1HeapRegion::LogOfHRGrainBytes); + __ beqz(tmp1, done); + + // crosses regions, storing null? @@ -18025,13 +19004,13 @@ index 00000000000..44b7ff1485f +#endif // CPU_LOONGARCH_GC_G1_G1GLOBALS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp new file mode 100644 -index 00000000000..12ef43b5a83 +index 00000000000..8a22401a623 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp -@@ -0,0 +1,453 @@ +@@ -0,0 +1,513 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2024, Loongson Technology. 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 @@ -18065,6 +19044,9 @@ index 00000000000..12ef43b5a83 +#include "runtime/jniHandles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" ++#ifdef COMPILER2 ++#include "gc/shared/c2/barrierSetC2.hpp" ++#endif // COMPILER2 + +#define __ masm-> + @@ -18330,20 +19312,6 @@ index 00000000000..12ef43b5a83 + // verify_tlab(); +} + -+void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, -+ Register var_size_in_bytes, -+ int con_size_in_bytes, -+ Register t1) { -+ assert(t1->is_valid(), "need temp reg"); -+ -+ __ ld_d(t1, Address(TREG, JavaThread::allocated_bytes_offset())); -+ if (var_size_in_bytes->is_valid()) -+ __ add_d(t1, t1, var_size_in_bytes); -+ else -+ __ addi_d(t1, t1, con_size_in_bytes); -+ __ st_d(t1, Address(TREG, JavaThread::allocated_bytes_offset())); -+} -+ +static volatile uint32_t _patching_epoch = 0; + +address BarrierSetAssembler::patching_epoch_addr() { @@ -18482,15 +19450,86 @@ index 00000000000..12ef43b5a83 + __ load_klass(obj, obj); // get klass + __ beqz(obj, error); // if klass is null it is broken +} ++ ++#ifdef COMPILER2 ++ ++OptoReg::Name BarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { ++ if (!OptoReg::is_reg(opto_reg)) { ++ return OptoReg::Bad; ++ } ++ ++ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); ++ if (vm_reg->is_FloatRegister()) { ++ return opto_reg & ~1; ++ } ++ ++ return opto_reg; ++} ++ ++#undef __ ++#define __ _masm-> ++ ++void SaveLiveRegisters::initialize(BarrierStubC2* stub) { ++ // Record registers that needs to be saved/restored ++ RegMaskIterator rmi(stub->preserve_set()); ++ while (rmi.has_next()) { ++ const OptoReg::Name opto_reg = rmi.next(); ++ if (OptoReg::is_reg(opto_reg)) { ++ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); ++ if (vm_reg->is_Register()) { ++ _gp_regs += RegSet::of(vm_reg->as_Register()); ++ } else if (vm_reg->is_FloatRegister()) { ++ if (UseLASX && vm_reg->next(7)) ++ _lasx_vp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); ++ else if (UseLSX && vm_reg->next(3)) ++ _lsx_vp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); ++ else ++ _fp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); ++ } else { ++ fatal("Unknown register type"); ++ } ++ } ++ } ++ ++ // Remove C-ABI SOE registers and scratch regs ++ _gp_regs -= RegSet::range(S0, S7) + RegSet::of(SP, SCR1, SCR2); ++} ++ ++SaveLiveRegisters::SaveLiveRegisters(MacroAssembler* masm, BarrierStubC2* stub) ++ : _masm(masm), ++ _gp_regs(), ++ _fp_regs(), ++ _lsx_vp_regs(), ++ _lasx_vp_regs() { ++ ++ // Figure out what registers to save/restore ++ initialize(stub); ++ ++ // Save registers ++ __ push(_gp_regs); ++ __ push_fpu(_fp_regs); ++ __ push_vp(_lsx_vp_regs /* UseLSX */); ++ __ push_vp(_lasx_vp_regs /* UseLASX */); ++} ++ ++SaveLiveRegisters::~SaveLiveRegisters() { ++ // Restore registers ++ __ pop_vp(_lasx_vp_regs /* UseLASX */); ++ __ pop_vp(_lsx_vp_regs /* UseLSX */); ++ __ pop_fpu(_fp_regs); ++ __ pop(_gp_regs); ++} ++ ++#endif // COMPILER2 diff --git a/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp new file mode 100644 -index 00000000000..0562518663f +index 00000000000..c096a378921 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.hpp -@@ -0,0 +1,147 @@ +@@ -0,0 +1,178 @@ +/* + * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2018, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2018, 2024, Loongson Technology. 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 @@ -18521,6 +19560,12 @@ index 00000000000..0562518663f +#include "gc/shared/barrierSetNMethod.hpp" +#include "memory/allocation.hpp" +#include "oops/access.hpp" ++#ifdef COMPILER2 ++#include "opto/optoreg.hpp" ++ ++class BarrierStubC2; ++class Node; ++#endif // COMPILER2 + +class InterpreterMacroAssembler; + @@ -18531,12 +19576,6 @@ index 00000000000..0562518663f +}; + +class BarrierSetAssembler: public CHeapObj { -+private: -+ void incr_allocated_bytes(MacroAssembler* masm, -+ Register var_size_in_bytes, -+ int con_size_in_bytes, -+ Register t1); -+ +public: + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) {} @@ -18632,8 +19671,39 @@ index 00000000000..0562518663f + static address patching_epoch_addr(); + static void clear_patching_epoch(); + static void increment_patching_epoch(); ++ ++#ifdef COMPILER2 ++ OptoReg::Name refine_register(const Node* node, ++ OptoReg::Name opto_reg); ++#endif // COMPILER2 +}; + ++#ifdef COMPILER2 ++ ++// This class saves and restores the registers that need to be preserved across ++// the runtime call represented by a given C2 barrier stub. Use as follows: ++// { ++// SaveLiveRegisters save(masm, stub); ++// .. ++// __ jalr(...); ++// .. ++// } ++class SaveLiveRegisters { ++private: ++ MacroAssembler* const _masm; ++ RegSet _gp_regs; ++ FloatRegSet _fp_regs; ++ FloatRegSet _lsx_vp_regs; ++ FloatRegSet _lasx_vp_regs; ++ ++public: ++ void initialize(BarrierStubC2* stub); ++ SaveLiveRegisters(MacroAssembler* masm, BarrierStubC2* stub); ++ ~SaveLiveRegisters(); ++}; ++ ++#endif // COMPILER2 ++ +#endif // CPU_LOONGARCH_GC_SHARED_BARRIERSETASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/gc/shared/barrierSetNMethod_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shared/barrierSetNMethod_loongarch.cpp new file mode 100644 @@ -19293,13 +20363,13 @@ index 00000000000..1fd8cff3904 +} diff --git a/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoahBarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoahBarrierSetAssembler_loongarch.cpp new file mode 100644 -index 00000000000..d9377db5503 +index 00000000000..3fc75ae74d0 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoahBarrierSetAssembler_loongarch.cpp -@@ -0,0 +1,783 @@ +@@ -0,0 +1,779 @@ +/* + * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. -+ * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -19408,17 +20478,13 @@ index 00000000000..d9377db5503 + assert_different_registers(obj, pre_val, tmp1, tmp2); + assert(pre_val != noreg && tmp1 != noreg && tmp2 != noreg, "expecting a register"); + -+ Address in_progress(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_active_offset())); + Address index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())); + Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); + + // Is marking active? -+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { -+ __ ld_w(tmp1, in_progress); -+ } else { -+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); -+ __ ld_b(tmp1, in_progress); -+ } ++ Address gc_state(TREG, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); ++ __ ld_bu(tmp1, gc_state); ++ __ test_bit(tmp1, tmp1, ShenandoahHeap::MARKING_BITPOS); + __ beqz(tmp1, done); + + // Do we need to load the previous value? @@ -20176,13 +21242,13 @@ index 00000000000..133bbbb0b89 +#endif // CPU_LOONGARCH_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoah_loongarch_64.ad b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoah_loongarch_64.ad new file mode 100644 -index 00000000000..2608ef13576 +index 00000000000..ca28ce64862 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoah_loongarch_64.ad -@@ -0,0 +1,232 @@ +@@ -0,0 +1,230 @@ +// +// Copyright (c) 2018, Red Hat, Inc. All rights reserved. -+// Copyright (c) 2023, Loongson Technology. All rights reserved. ++// Copyright (c) 2023, 2024, Loongson Technology. 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 @@ -20212,16 +21278,14 @@ index 00000000000..2608ef13576 + +encode %{ + enc_class loongarch_enc_cmpxchg_oop_shenandoah(indirect mem, mRegP oldval, mRegP newval, mRegI res) %{ -+ MacroAssembler _masm(&cbuf); + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} + + enc_class loongarch_enc_cmpxchg_acq_oop_shenandoah(indirect mem, mRegP oldval, mRegP newval, mRegI res) %{ -+ MacroAssembler _masm(&cbuf); + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} +%} @@ -20247,7 +21311,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} + @@ -20275,7 +21339,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} + @@ -20291,7 +21355,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ true, $res$$Register); + %} + @@ -20307,7 +21371,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ true, $res$$Register); + %} + @@ -20323,7 +21387,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ true, $res$$Register); + %} + @@ -20339,7 +21403,7 @@ index 00000000000..2608ef13576 + + ins_encode %{ + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ true, $res$$Register); + %} + @@ -20355,7 +21419,7 @@ index 00000000000..2608ef13576 + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} + @@ -20372,7 +21436,7 @@ index 00000000000..2608ef13576 + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} + @@ -20389,7 +21453,7 @@ index 00000000000..2608ef13576 + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} + @@ -20406,7 +21470,7 @@ index 00000000000..2608ef13576 + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop + Address addr(as_Register($mem$$base), 0); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, ++ ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} + @@ -21259,13 +22323,13 @@ index 00000000000..3134c3d07f8 +#endif // CPU_LOONGARCH_GC_X_XGLOBALS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/gc/x/x_loongarch_64.ad b/src/hotspot/cpu/loongarch/gc/x/x_loongarch_64.ad new file mode 100644 -index 00000000000..c4e77f08b4f +index 00000000000..671c9318857 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/x/x_loongarch_64.ad @@ -0,0 +1,256 @@ +// +// Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++// Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -21297,7 +22361,7 @@ index 00000000000..c4e77f08b4f + +source %{ + -+static void x_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, uint8_t barrier_data) { ++static void x_load_barrier(MacroAssembler *masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, uint8_t barrier_data) { + if (barrier_data == XLoadBarrierElided) { + return; + } @@ -21308,13 +22372,13 @@ index 00000000000..c4e77f08b4f + __ bind(*stub->continuation()); +} + -+static void x_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { ++static void x_load_barrier_slow_path(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { + XLoadBarrierStubC2* const stub = XLoadBarrierStubC2::create(node, ref_addr, ref, tmp, XLoadBarrierStrong); + __ b(*stub->entry()); + __ bind(*stub->continuation()); +} + -+static void x_compare_and_swap(MacroAssembler& _masm, const MachNode* node, ++static void x_compare_and_swap(MacroAssembler* masm, const MachNode* node, + Register res, Register mem, Register oldval, Register newval, + Register tmp, bool weak, bool acquire) { + // z-specific load barrier requires strong CAS operations. @@ -21334,14 +22398,14 @@ index 00000000000..c4e77f08b4f + __ ld_d(AT, Address(TREG, XThreadLocalData::address_bad_mask_offset())); + __ andr(AT, AT, tmp); + __ beqz(AT, good); -+ x_load_barrier_slow_path(_masm, node, addr, tmp, res /* used as tmp */); ++ x_load_barrier_slow_path(masm, node, addr, tmp, res /* used as tmp */); + __ cmpxchg(addr, oldval, newval, tmp, false /* retold */, acquire /* acquire */, weak /* weak */, false /* exchange */); + __ move(res, tmp); + __ bind(good); + } +} + -+static void x_compare_and_exchange(MacroAssembler& _masm, const MachNode* node, ++static void x_compare_and_exchange(MacroAssembler* masm, const MachNode* node, + Register res, Register mem, Register oldval, Register newval, Register tmp, + bool weak, bool acquire) { + // z-specific load barrier requires strong CAS operations. @@ -21354,7 +22418,7 @@ index 00000000000..c4e77f08b4f + __ ld_d(tmp, Address(TREG, XThreadLocalData::address_bad_mask_offset())); + __ andr(tmp, tmp, res); + __ beqz(tmp, good); -+ x_load_barrier_slow_path(_masm, node, addr, res /* ref */, tmp); ++ x_load_barrier_slow_path(masm, node, addr, res /* ref */, tmp); + __ cmpxchg(addr, oldval, newval, res, false /* retold */, acquire /* barrier */, weak /* weak */, true /* exchange */); + __ bind(good); + } @@ -21377,7 +22441,7 @@ index 00000000000..c4e77f08b4f + Address ref_addr = Address(as_Register($mem$$base), as_Register($mem$$index), Address::no_scale, $mem$$disp); + __ block_comment("xLoadP"); + __ ld_d($dst$$Register, ref_addr); -+ x_load_barrier(_masm, this, ref_addr, $dst$$Register, $tmp$$Register, barrier_data()); ++ x_load_barrier(masm, this, ref_addr, $dst$$Register, $tmp$$Register, barrier_data()); + %} + + ins_pipe(pipe_slow); @@ -21394,7 +22458,7 @@ index 00000000000..c4e77f08b4f + format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndSwapP"); -+ x_compare_and_swap(_masm, this, ++ x_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $tmp$$Register, false /* weak */, false /* acquire */); + %} @@ -21412,7 +22476,7 @@ index 00000000000..c4e77f08b4f + format %{ "CMPXCHG acq $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndSwapP_acq"); -+ x_compare_and_swap(_masm, this, ++ x_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $tmp$$Register, false /* weak */, true /* acquire */); + %} @@ -21432,7 +22496,7 @@ index 00000000000..c4e77f08b4f + format %{ "weak CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndSwapPWeak"); -+ x_compare_and_swap(_masm, this, ++ x_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $tmp$$Register, true /* weak */, false /* acquire */); + %} @@ -21450,7 +22514,7 @@ index 00000000000..c4e77f08b4f + format %{ "weak CMPXCHG acq $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndSwapPWeak_acq"); -+ x_compare_and_swap(_masm, this, ++ x_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $tmp$$Register, true /* weak */, true /* acquire */); + %} @@ -21472,7 +22536,7 @@ index 00000000000..c4e77f08b4f + format %{ "CMPXCHG $res, $mem, $oldval, $newval; as ptr; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndExchangeP"); -+ x_compare_and_exchange(_masm, this, ++ x_compare_and_exchange(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, $tmp$$Register, + false /* weak */, false /* acquire */); + %} @@ -21493,7 +22557,7 @@ index 00000000000..c4e77f08b4f + format %{ "CMPXCHG acq $res, $mem, $oldval, $newval; as ptr; ptr" %} + ins_encode %{ + __ block_comment("xCompareAndExchangeP_acq"); -+ x_compare_and_exchange(_masm, this, ++ x_compare_and_exchange(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, $tmp$$Register, + false /* weak */, true /* acquire */); + %} @@ -21514,7 +22578,7 @@ index 00000000000..c4e77f08b4f + Register addr = $mem$$Register; + __ block_comment("xGetAndSetP"); + __ amswap_db_d(prev, newv, addr); -+ x_load_barrier(_masm, this, Address(noreg, 0), prev, $tmp$$Register, barrier_data()); ++ x_load_barrier(masm, this, Address(noreg, 0), prev, $tmp$$Register, barrier_data()); + %} + + ins_pipe(pipe_slow); @@ -21721,13 +22785,13 @@ index 00000000000..93ea4144072 +#endif // CPU_LOONGARCH64_GC_Z_ZADDRESS_LOONGARCH64_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.cpp new file mode 100644 -index 00000000000..427a6f9c24a +index 00000000000..d9d435e5326 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.cpp -@@ -0,0 +1,1226 @@ +@@ -0,0 +1,1147 @@ +/* + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -22755,87 +23819,6 @@ index 00000000000..427a6f9c24a + +#ifdef COMPILER2 + -+OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { -+ if (!OptoReg::is_reg(opto_reg)) { -+ return OptoReg::Bad; -+ } -+ -+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -+ if (vm_reg->is_FloatRegister()) { -+ return opto_reg & ~1; -+ } -+ -+ return opto_reg; -+} -+ -+#undef __ -+#define __ _masm-> -+ -+class ZSaveLiveRegisters { -+private: -+ MacroAssembler* const _masm; -+ RegSet _gp_regs; -+ FloatRegSet _fp_regs; -+ FloatRegSet _lsx_vp_regs; -+ FloatRegSet _lasx_vp_regs; -+ -+public: -+ void initialize(ZBarrierStubC2* stub) { -+ // Record registers that needs to be saved/restored -+ RegMaskIterator rmi(stub->live()); -+ while (rmi.has_next()) { -+ const OptoReg::Name opto_reg = rmi.next(); -+ if (OptoReg::is_reg(opto_reg)) { -+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -+ if (vm_reg->is_Register()) { -+ _gp_regs += RegSet::of(vm_reg->as_Register()); -+ } else if (vm_reg->is_FloatRegister()) { -+ if (UseLASX && vm_reg->next(7)) -+ _lasx_vp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); -+ else if (UseLSX && vm_reg->next(3)) -+ _lsx_vp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); -+ else -+ _fp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); -+ } else { -+ fatal("Unknown register type"); -+ } -+ } -+ } -+ -+ // Remove C-ABI SOE registers, scratch regs and _ref register that will be updated -+ if (stub->result() != noreg) { -+ _gp_regs -= RegSet::range(S0, S7) + RegSet::of(SP, SCR1, SCR2, stub->result()); -+ } else { -+ _gp_regs -= RegSet::range(S0, S7) + RegSet::of(SP, SCR1, SCR2); -+ } -+ } -+ -+ ZSaveLiveRegisters(MacroAssembler* masm, ZBarrierStubC2* stub) : -+ _masm(masm), -+ _gp_regs(), -+ _fp_regs(), -+ _lsx_vp_regs(), -+ _lasx_vp_regs() { -+ -+ // Figure out what registers to save/restore -+ initialize(stub); -+ -+ // Save registers -+ __ push(_gp_regs); -+ __ push_fpu(_fp_regs); -+ __ push_vp(_lsx_vp_regs /* UseLSX */); -+ __ push_vp(_lasx_vp_regs /* UseLASX */); -+ } -+ -+ ~ZSaveLiveRegisters() { -+ // Restore registers -+ __ pop_vp(_lasx_vp_regs /* UseLASX */); -+ __ pop_vp(_lsx_vp_regs /* UseLSX */); -+ __ pop_fpu(_fp_regs); -+ __ pop(_gp_regs); -+ } -+}; -+ +#undef __ +#define __ _masm-> + @@ -22896,6 +23879,7 @@ index 00000000000..427a6f9c24a +#define __ masm-> + +void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { ++ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); + BLOCK_COMMENT("ZLoadBarrierStubC2"); + + // Stub entry @@ -22904,7 +23888,7 @@ index 00000000000..427a6f9c24a + } + + { -+ ZSaveLiveRegisters save_live_registers(masm, stub); ++ SaveLiveRegisters save_live_registers(masm, stub); + ZSetupArguments setup_arguments(masm, stub); + __ MacroAssembler::call_VM_leaf_base(stub->slow_path(), 2); + } @@ -22913,6 +23897,7 @@ index 00000000000..427a6f9c24a +} + +void ZBarrierSetAssembler::generate_c2_store_barrier_stub(MacroAssembler* masm, ZStoreBarrierStubC2* stub) const { ++ Assembler::InlineSkippedInstructionsCounter skipped_counter(masm); + BLOCK_COMMENT("ZStoreBarrierStubC2"); + + // Stub entry @@ -22934,7 +23919,7 @@ index 00000000000..427a6f9c24a + __ bind(slow); + + { -+ ZSaveLiveRegisters save_live_registers(masm, stub); ++ SaveLiveRegisters save_live_registers(masm, stub); + __ lea(A0, stub->ref_addr()); + + if (stub->is_native()) { @@ -22953,13 +23938,13 @@ index 00000000000..427a6f9c24a +#endif // COMPILER2 diff --git a/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.hpp new file mode 100644 -index 00000000000..754f042f749 +index 00000000000..b8c35df2bf2 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/z/zBarrierSetAssembler_loongarch.hpp -@@ -0,0 +1,192 @@ +@@ -0,0 +1,189 @@ +/* + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -23138,9 +24123,6 @@ index 00000000000..754f042f749 +#endif // COMPILER1 + +#ifdef COMPILER2 -+ OptoReg::Name refine_register(const Node* node, -+ OptoReg::Name opto_reg); -+ + void generate_c2_load_barrier_stub(MacroAssembler* masm, + ZLoadBarrierStubC2* stub) const; + void generate_c2_store_barrier_stub(MacroAssembler* masm, @@ -23187,13 +24169,13 @@ index 00000000000..3e012e31420 +#endif // CPU_LOONGARCH_GC_Z_ZGLOBALS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/gc/z/z_loongarch_64.ad b/src/hotspot/cpu/loongarch/gc/z/z_loongarch_64.ad new file mode 100644 -index 00000000000..7a50810acda +index 00000000000..4125f803d69 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/z/z_loongarch_64.ad @@ -0,0 +1,250 @@ +// +// Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++// Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -23227,7 +24209,7 @@ index 00000000000..7a50810acda + +#include "gc/z/zBarrierSetAssembler.hpp" + -+static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { ++static void z_load_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { + if (node->barrier_data() == ZBarrierElided) { + __ z_uncolor(ref); + } else { @@ -23247,33 +24229,33 @@ index 00000000000..7a50810acda + } +} + -+static void z_store_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) { ++static void z_store_barrier(MacroAssembler* masm, const MachNode* node, Address ref_addr, Register rnew_zaddress, Register rnew_zpointer, Register tmp, bool is_atomic) { + if (node->barrier_data() == ZBarrierElided) { + __ z_color(rnew_zpointer, rnew_zaddress, tmp); + } else { + bool is_native = (node->barrier_data() & ZBarrierNative) != 0; + ZStoreBarrierStubC2* const stub = ZStoreBarrierStubC2::create(node, ref_addr, rnew_zaddress, rnew_zpointer, is_native, is_atomic); + ZBarrierSetAssembler* bs_asm = ZBarrierSet::assembler(); -+ bs_asm->store_barrier_fast(&_masm, ref_addr, rnew_zaddress, rnew_zpointer, tmp, true /* in_nmethod */, is_atomic, *stub->entry(), *stub->continuation()); ++ bs_asm->store_barrier_fast(masm, ref_addr, rnew_zaddress, rnew_zpointer, tmp, true /* in_nmethod */, is_atomic, *stub->entry(), *stub->continuation()); + } +} + -+static void z_compare_and_swap(MacroAssembler& _masm, const MachNode* node, ++static void z_compare_and_swap(MacroAssembler* masm, const MachNode* node, + Register res, Register mem, Register oldval, Register newval, + Register oldval_tmp, Register newval_tmp, Register tmp, bool acquire) { + Address addr(mem); + __ z_color(oldval_tmp, oldval, tmp); -+ z_store_barrier(_masm, node, addr, newval, newval_tmp, tmp, true /* is_atomic */); ++ z_store_barrier(masm, node, addr, newval, newval_tmp, tmp, true /* is_atomic */); + __ cmpxchg(addr, oldval_tmp, newval_tmp, res, false /* retold */, acquire /* acquire */, + false /* weak */, false /* exchange */); +} + -+static void z_compare_and_exchange(MacroAssembler& _masm, const MachNode* node, ++static void z_compare_and_exchange(MacroAssembler* masm, const MachNode* node, + Register res, Register mem, Register oldval, Register newval, + Register oldval_tmp, Register newval_tmp, Register tmp, bool acquire) { + Address addr(mem); + __ z_color(oldval_tmp, oldval, tmp); -+ z_store_barrier(_masm, node, addr, newval, newval_tmp, tmp, true /* is_atomic */); ++ z_store_barrier(masm, node, addr, newval, newval_tmp, tmp, true /* is_atomic */); + __ cmpxchg(addr, oldval_tmp, newval_tmp, res, false /* retold */, acquire /* acquire */, + false /* weak */, true /* exchange */); + __ z_uncolor(res); @@ -23296,7 +24278,7 @@ index 00000000000..7a50810acda + Address ref_addr = Address(as_Register($mem$$base), as_Register($mem$$index), Address::no_scale, $mem$$disp); + __ block_comment("zLoadP"); + __ ld_d($dst$$Register, ref_addr); -+ z_load_barrier(_masm, this, ref_addr, $dst$$Register, $tmp$$Register); ++ z_load_barrier(masm, this, ref_addr, $dst$$Register, $tmp$$Register); + %} + + ins_pipe(pipe_slow); @@ -23314,7 +24296,7 @@ index 00000000000..7a50810acda + ins_encode %{ + Address ref_addr = Address(as_Register($mem$$base), as_Register($mem$$index), Address::no_scale, $mem$$disp); + __ block_comment("zStoreP"); -+ z_store_barrier(_masm, this, ref_addr, $src$$Register, $tmp1$$Register, $tmp2$$Register, false /* is_atomic */); ++ z_store_barrier(masm, this, ref_addr, $src$$Register, $tmp1$$Register, $tmp2$$Register, false /* is_atomic */); + __ st_d($tmp1$$Register, ref_addr); + %} + ins_pipe(pipe_slow); @@ -23332,7 +24314,7 @@ index 00000000000..7a50810acda + ins_encode %{ + Address ref_addr = Address(as_Register($mem$$base), as_Register($mem$$index), Address::no_scale, $mem$$disp); + __ block_comment("zStoreP null"); -+ z_store_barrier(_masm, this, ref_addr, noreg, $tmp1$$Register, $tmp2$$Register, false /* is_atomic */); ++ z_store_barrier(masm, this, ref_addr, noreg, $tmp1$$Register, $tmp2$$Register, false /* is_atomic */); + __ st_d($tmp1$$Register, ref_addr); + %} + ins_pipe(pipe_slow); @@ -23350,7 +24332,7 @@ index 00000000000..7a50810acda + format %{ "zCompareAndSwapP $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("zCompareAndSwapP"); -+ z_compare_and_swap(_masm, this, ++ z_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $oldval_tmp$$Register, $newval_tmp$$Register, $tmp$$Register, false /* acquire */); + %} @@ -23370,7 +24352,7 @@ index 00000000000..7a50810acda + format %{ "zCompareAndSwapP acq $res, $mem, $oldval, $newval; as bool; ptr" %} + ins_encode %{ + __ block_comment("zCompareAndSwapP_acq"); -+ z_compare_and_swap(_masm, this, ++ z_compare_and_swap(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $oldval_tmp$$Register, $newval_tmp$$Register, $tmp$$Register, true /* acquire */); + %} @@ -23392,7 +24374,7 @@ index 00000000000..7a50810acda + format %{ "zCompareAndExchangeP $res, $mem, $oldval, $newval; as ptr; ptr" %} + ins_encode %{ + __ block_comment("zCompareAndExchangeP"); -+ z_compare_and_exchange(_masm, this, ++ z_compare_and_exchange(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $oldval_tmp$$Register, $newval_tmp$$Register, $tmp$$Register, false /* acquire */); + %} @@ -23413,7 +24395,7 @@ index 00000000000..7a50810acda + format %{ "zCompareAndExchangeP acq $res, $mem, $oldval, $newval; as ptr; ptr" %} + ins_encode %{ + __ block_comment("zCompareAndExchangeP_acq"); -+ z_compare_and_exchange(_masm, this, ++ z_compare_and_exchange(masm, this, + $res$$Register, $mem$$Register, $oldval$$Register, $newval$$Register, + $oldval_tmp$$Register, $newval_tmp$$Register, $tmp$$Register, true /* acquire */); + %} @@ -23433,7 +24415,7 @@ index 00000000000..7a50810acda + Register newv = $newv$$Register; + Register addr = $mem$$Register; + __ block_comment("zGetAndSetP"); -+ z_store_barrier(_masm, this, Address(addr, 0), newv, prev, $tmp1$$Register, true /* is_atomic */); ++ z_store_barrier(masm, this, Address(addr, 0), newv, prev, $tmp1$$Register, true /* is_atomic */); + __ amswap_db_d($tmp2$$Register, prev, addr); + __ move(prev, $tmp2$$Register); + __ z_uncolor(prev); @@ -23443,13 +24425,13 @@ index 00000000000..7a50810acda +%} diff --git a/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp b/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp new file mode 100644 -index 00000000000..2306c5bc6d1 +index 00000000000..65e81626fdc --- /dev/null +++ b/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp -@@ -0,0 +1,58 @@ +@@ -0,0 +1,62 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -23502,18 +24484,22 @@ index 00000000000..2306c5bc6d1 + +#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY + ++// The expected size in bytes of a cache line. +#define DEFAULT_CACHE_LINE_SIZE 64 + ++// The default padding size for data structures to avoid false sharing. ++#define DEFAULT_PADDING_SIZE DEFAULT_CACHE_LINE_SIZE ++ +#endif // CPU_LOONGARCH_GLOBALDEFINITIONS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/globals_loongarch.hpp b/src/hotspot/cpu/loongarch/globals_loongarch.hpp new file mode 100644 -index 00000000000..e38b0401bee +index 00000000000..02b9329d3d7 --- /dev/null +++ b/src/hotspot/cpu/loongarch/globals_loongarch.hpp -@@ -0,0 +1,125 @@ +@@ -0,0 +1,124 @@ +/* + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -23589,7 +24575,6 @@ index 00000000000..e38b0401bee + +#define ARCH_FLAGS(develop, \ + product, \ -+ notproduct, \ + range, \ + constraint) \ + \ @@ -23636,94 +24621,6 @@ index 00000000000..e38b0401bee +// end of ARCH_FLAGS + +#endif // CPU_LOONGARCH_GLOBALS_LOONGARCH_HPP -diff --git a/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp b/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp -new file mode 100644 -index 00000000000..c53d50d78f6 ---- /dev/null -+++ b/src/hotspot/cpu/loongarch/icBuffer_loongarch.cpp -@@ -0,0 +1,82 @@ -+/* -+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "asm/macroAssembler.hpp" -+#include "asm/macroAssembler.inline.hpp" -+#include "code/icBuffer.hpp" -+#include "gc/shared/collectedHeap.inline.hpp" -+#include "interpreter/bytecodes.hpp" -+#include "memory/resourceArea.hpp" -+#include "nativeInst_loongarch.hpp" -+#include "oops/oop.inline.hpp" -+ -+ -+int InlineCacheBuffer::ic_stub_code_size() { -+ return NativeMovConstReg::instruction_size + // patchable_li52() == 3 ins -+ NativeGeneralJump::instruction_size; // patchable_jump() == 2 ins -+} -+ -+ -+// The use IC_Klass refer to SharedRuntime::gen_i2c2i_adapters -+void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, -+ void* cached_value, -+ address entry_point) { -+ ResourceMark rm; -+ CodeBuffer code(code_begin, ic_stub_code_size()); -+ MacroAssembler* masm = new MacroAssembler(&code); -+ // Note: even though the code contains an embedded value, we do not need reloc info -+ // because -+ // (1) the value is old (i.e., doesn't matter for scavenges) -+ // (2) these ICStubs are removed *before* a GC happens, so the roots disappear -+ -+#define __ masm-> -+ address start = __ pc(); -+ __ patchable_li52(IC_Klass, (long)cached_value); -+ __ jmp(entry_point, relocInfo::runtime_call_type); -+ -+ ICache::invalidate_range(code_begin, InlineCacheBuffer::ic_stub_code_size()); -+ assert(__ pc() - start == ic_stub_code_size(), "must be"); -+#undef __ -+} -+ -+ -+address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) { -+ // move -> jump -> entry -+ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); -+ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); -+ return jump->jump_destination(); -+} -+ -+ -+void* InlineCacheBuffer::ic_buffer_cached_value(address code_begin) { -+ // double check the instructions flow -+ NativeMovConstReg* move = nativeMovConstReg_at(code_begin); -+ NativeGeneralJump* jump = nativeGeneralJump_at(move->next_instruction_address()); -+ -+ // cached value is the data arg of NativeMovConstReg -+ void* cached_value = (void*)move->data(); -+ return cached_value; -+} diff --git a/src/hotspot/cpu/loongarch/icache_loongarch.cpp b/src/hotspot/cpu/loongarch/icache_loongarch.cpp new file mode 100644 index 00000000000..59906711428 @@ -24098,13 +24995,13 @@ index 00000000000..85bed067c49 +#endif // CPU_LOONGARCH_INTERP_MASM_LOONGARCH_64_HPP diff --git a/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp b/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp new file mode 100644 -index 00000000000..0e9e66940b4 +index 00000000000..dcc20ab42d1 --- /dev/null +++ b/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp -@@ -0,0 +1,1884 @@ +@@ -0,0 +1,1861 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -24238,25 +25135,23 @@ index 00000000000..0e9e66940b4 + restore_locals(); +} + -+ +void InterpreterMacroAssembler::check_and_handle_popframe(Register java_thread) { + if (JvmtiExport::can_pop_frame()) { + Label L; + // Initiate popframe handling only if it is not already being -+ // processed. If the flag has the popframe_processing bit set, it -+ // means that this code is called *during* popframe handling - we ++ // processed. If the flag has the popframe_processing bit set, ++ // it means that this code is called *during* popframe handling - we + // don't want to reenter. + // This method is only called just after the call into the vm in + // call_VM_base, so the arg registers are available. -+ // Not clear if any other register is available, so load AT twice + assert(AT != java_thread, "check"); -+ ld_w(AT, java_thread, in_bytes(JavaThread::popframe_condition_offset())); -+ andi(AT, AT, JavaThread::popframe_pending_bit); -+ beq(AT, R0, L); -+ -+ ld_w(AT, java_thread, in_bytes(JavaThread::popframe_condition_offset())); -+ andi(AT, AT, JavaThread::popframe_processing_bit); -+ bne(AT, R0, L); ++ ld_w(AT, Address(java_thread, JavaThread::popframe_condition_offset())); ++ test_bit(T8, AT, exact_log2(JavaThread::popframe_pending_bit)); ++ beqz(T8, L); ++ test_bit(T8, AT, exact_log2(JavaThread::popframe_processing_bit)); ++ bnez(T8, L); ++ // Call Interpreter::remove_activation_preserving_args_entry() to get the ++ // address of the same-named entrypoint in the generated interpreter code. + call_VM_leaf(CAST_FROM_FN_PTR(address, Interpreter::remove_activation_preserving_args_entry)); + jr(V0); + bind(L); @@ -24348,12 +25243,6 @@ index 00000000000..0e9e66940b4 + get_2_byte_integer_at_bcp(index, AT, bcp_offset); + } else if (index_size == sizeof(u4)) { + get_4_byte_integer_at_bcp(index, bcp_offset); -+ // Check if the secondary index definition is still ~x, otherwise -+ // we have to change the following assembler code to calculate the -+ // plain index. -+ assert(ConstantPool::decode_invokedynamic_index(~123) == 123, "else change next line"); -+ nor(index, index, R0); -+ slli_w(index, index, 0); + } else if (index_size == sizeof(u1)) { + ld_bu(index, BCP, bcp_offset); + } else { @@ -24400,6 +25289,8 @@ index 00000000000..0e9e66940b4 + ld_d(cache, Address(cache, ConstantPoolCache::field_entries_offset())); + addi_d(cache, cache, Array::base_offset_in_bytes()); + add_d(cache, cache, index); ++ // Prevents stale data from being read after the bytecode is patched to the fast bytecode ++ membar(MacroAssembler::LoadLoad); +} + +void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) { @@ -24624,7 +25515,7 @@ index 00000000000..0e9e66940b4 + if (needs_thread_local_poll) { + NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); + ld_d(SCR1, TREG, in_bytes(JavaThread::polling_word_offset())); -+ andi(SCR1, SCR1, SafepointMechanism::poll_bit()); ++ test_bit(SCR1, SCR1, exact_log2(SafepointMechanism::poll_bit())); + bnez(SCR1, safepoint); + } + @@ -24722,7 +25613,7 @@ index 00000000000..0e9e66940b4 + // get method access flags + ld_d(AT, FP, frame::interpreter_frame_method_offset * wordSize); + ld_wu(AT, AT, in_bytes(Method::access_flags_offset())); -+ andi(AT, AT, JVM_ACC_SYNCHRONIZED); ++ test_bit(AT, AT, exact_log2(JVM_ACC_SYNCHRONIZED)); + beqz(AT, unlocked); + + // Don't unlock anything if the _do_not_unlock_if_synchronized flag is set. @@ -24887,13 +25778,11 @@ index 00000000000..0e9e66940b4 + if (DiagnoseSyncOnValueBasedClasses != 0) { + load_klass(tmp_reg, scr_reg); + ld_w(tmp_reg, Address(tmp_reg, Klass::access_flags_offset())); -+ li(AT, JVM_ACC_IS_VALUE_BASED_CLASS); -+ andr(AT, AT, tmp_reg); -+ bnez(AT, slow_case); ++ test_bit(tmp_reg, tmp_reg, exact_log2(JVM_ACC_IS_VALUE_BASED_CLASS)); ++ bnez(tmp_reg, slow_case); + } + + if (LockingMode == LM_LIGHTWEIGHT) { -+ ld_d(tmp_reg, Address(scr_reg, oopDesc::mark_offset_in_bytes())); + lightweight_lock(scr_reg, tmp_reg, SCR1, SCR2, slow_case); + b(count); + } else if (LockingMode == LM_LEGACY) { @@ -24980,21 +25869,6 @@ index 00000000000..0e9e66940b4 + if (LockingMode == LM_LIGHTWEIGHT) { + Label slow_case; + -+ // Check for non-symmetric locking. This is allowed by the spec and the interpreter -+ // must handle it. -+ Register tmp = SCR1; -+ // First check for lock-stack underflow. -+ ld_wu(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); -+ li(AT, (unsigned)LockStack::start_offset()); -+ bgeu(AT, tmp, slow_case); -+ // Then check if the top of the lock-stack matches the unlocked object. -+ addi_w(tmp, tmp, -oopSize); -+ ldx_d(tmp, TREG, tmp); -+ bne(scr_reg, tmp, slow_case); -+ -+ ld_d(hdr_reg, Address(scr_reg, oopDesc::mark_offset_in_bytes())); -+ andi(AT, hdr_reg, markWord::monitor_value); -+ bnez(AT, slow_case); + lightweight_unlock(scr_reg, hdr_reg, tmp_reg, SCR1, slow_case); + b(count); + bind(slow_case); @@ -25581,19 +26455,19 @@ index 00000000000..0e9e66940b4 + addi_d(AT, T4, -T_BOOLEAN); + bne(AT, R0, notBool); + andi(result, result, 0x1); -+ beq(R0, R0, done); ++ b(done); + + bind(notBool); + addi_d(AT, T4, -T_BYTE); + bne(AT, R0, notByte); + ext_w_b(result, result); -+ beq(R0, R0, done); ++ b(done); + + bind(notByte); + addi_d(AT, T4, -T_CHAR); + bne(AT, R0, notChar); + bstrpick_d(result, result, 15, 0); -+ beq(R0, R0, done); ++ b(done); + + bind(notChar); + ext_w_h(result, result); @@ -25646,7 +26520,7 @@ index 00000000000..0e9e66940b4 + bstrpick_d(T5, obj, 63, 2); + beqz(T5, next); + -+ andi(T5, obj, TypeEntries::type_unknown); ++ test_bit(T5, obj, exact_log2(TypeEntries::type_unknown)); + bnez(T5, next); + + beqz(AT, none); @@ -26418,13 +27292,13 @@ index 00000000000..79a65cd5be1 +#endif // CPU_LOONGARCH_JAVAFRAMEANCHOR_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp b/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp new file mode 100644 -index 00000000000..8e8e548e610 +index 00000000000..eb697ec6793 --- /dev/null +++ b/src/hotspot/cpu/loongarch/jniFastGetField_loongarch_64.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -26498,9 +27372,9 @@ index 00000000000..8e8e548e610 + + __ li(counter_addr, SafepointSynchronize::safepoint_counter_addr()); + __ ld_w(counter_prev_val, counter_addr, 0); -+ + // Parameters(A0~A3) should not be modified, since they will be used in slow path -+ __ andi(tmp1, counter_prev_val, 1); ++ __ test_bit(tmp1, counter_prev_val, exact_log2(1)); ++ // An even value means there are no ongoing safepoint operations + __ bnez(tmp1, slow); + + if (JvmtiExport::can_post_field_access()) { @@ -26752,13 +27626,13 @@ index 00000000000..3388ddb9db7 +#endif // CPU_LOONGARCH_JNITYPES_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp b/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp new file mode 100644 -index 00000000000..8679369b78f +index 00000000000..9235eda44c5 --- /dev/null +++ b/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -26850,7 +27724,7 @@ index 00000000000..8679369b78f +void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, JVMCI_TRAPS) { + address pc = _instructions->start() + pc_offset; + NativeInstruction* inst = nativeInstruction_at(pc); -+ if (inst->is_pcaddu12i_add()) { ++ if (inst->is_pcaddi()) { + address dest = _constants->start() + data_offset; + _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); + JVMCI_event_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); @@ -26984,13 +27858,13 @@ index 00000000000..80dff0c7626 + diff --git a/src/hotspot/cpu/loongarch/loongarch_64.ad b/src/hotspot/cpu/loongarch/loongarch_64.ad new file mode 100644 -index 00000000000..c725468b09f +index 00000000000..a9275ba04c3 --- /dev/null +++ b/src/hotspot/cpu/loongarch/loongarch_64.ad -@@ -0,0 +1,15964 @@ +@@ -0,0 +1,15454 @@ +// +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++// Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -27582,6 +28456,10 @@ index 00000000000..c725468b09f + return _NO_CR_REG_mask; +%} + ++reg_class no_FP_reg %{ ++ return _NO_FP_REG_mask; ++%} ++ +reg_class p_has_s6_reg %{ + return _PTR_HAS_S6_REG_mask; +%} @@ -27789,6 +28667,7 @@ index 00000000000..c725468b09f +extern RegMask _ANY_REG_mask; +extern RegMask _PTR_REG_mask; +extern RegMask _NO_CR_REG_mask; ++extern RegMask _NO_FP_REG_mask; +extern RegMask _PTR_HAS_S6_REG_mask; + +class CallStubImpl { @@ -27813,8 +28692,8 @@ index 00000000000..c725468b09f + + public: + -+ static int emit_exception_handler(CodeBuffer &cbuf); -+ static int emit_deopt_handler(CodeBuffer& cbuf); ++ static int emit_exception_handler(C2_MacroAssembler *masm); ++ static int emit_deopt_handler(C2_MacroAssembler* masm); + + static uint size_exception_handler() { + // NativeCall instruction size is the same as NativeJump. @@ -27862,12 +28741,13 @@ index 00000000000..c725468b09f +#define V0_num A0_num +#define V0_H_num A0_H_num + -+#define __ _masm. ++#define __ masm-> + +RegMask _ANY_REG32_mask; +RegMask _ANY_REG_mask; +RegMask _PTR_REG_mask; +RegMask _NO_CR_REG_mask; ++RegMask _NO_FP_REG_mask; +RegMask _PTR_HAS_S6_REG_mask; + +void reg_mask_init() { @@ -27900,6 +28780,9 @@ index 00000000000..c725468b09f + _NO_CR_REG_mask = _PTR_REG_mask; + _NO_CR_REG_mask.SUBTRACT(_T0_LONG_REG_mask); + ++ _NO_FP_REG_mask = _PTR_REG_mask; ++ _NO_FP_REG_mask.Remove(OptoReg::as_OptoReg(r22->as_VMReg())); ++ + _PTR_HAS_S6_REG_mask.OR(_S6_LONG_REG_mask); +} + @@ -27916,10 +28799,9 @@ index 00000000000..c725468b09f + +// Emit exception handler code. +// Stuff framesize into a register and call a VM stub routine. -+int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) { ++int HandlerImpl::emit_exception_handler(C2_MacroAssembler* masm) { + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. -+ C2_MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_exception_handler()); + if (base == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); @@ -27930,7 +28812,6 @@ index 00000000000..c725468b09f + + __ block_comment("; emit_exception_handler"); + -+ cbuf.set_insts_mark(); + __ relocate(relocInfo::runtime_call_type); + __ patchable_jump((address)OptoRuntime::exception_blob()->entry_point()); + assert(__ offset() - offset <= (int) size_exception_handler(), "overflow"); @@ -27939,10 +28820,9 @@ index 00000000000..c725468b09f +} + +// Emit deopt handler code. -+int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) { ++int HandlerImpl::emit_deopt_handler(C2_MacroAssembler* masm) { + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. -+ C2_MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_deopt_handler()); + if (base == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); @@ -27953,7 +28833,6 @@ index 00000000000..c725468b09f + + __ block_comment("; emit_deopt_handler"); + -+ cbuf.set_insts_mark(); + __ relocate(relocInfo::runtime_call_type); + __ patchable_call(SharedRuntime::deopt_blob()->unpack()); + assert(__ offset() - offset <= (int) size_deopt_handler(), "overflow"); @@ -28005,7 +28884,7 @@ index 00000000000..c725468b09f + return true; // Per default match rules are supported. +} + -+bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) { ++bool Matcher::match_rule_supported_auto_vectorization(int opcode, int vlen, BasicType bt) { + return match_rule_supported_vector(opcode, vlen, bt); +} + @@ -28137,7 +29016,7 @@ index 00000000000..c725468b09f + return -1; +} + -+int Matcher::superword_max_vector_size(const BasicType bt) { ++int Matcher::max_vector_size_auto_vectorization(const BasicType bt) { + return Matcher::max_vector_size(bt); +} + @@ -28300,8 +29179,7 @@ index 00000000000..c725468b09f +} +#endif + -+void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc* ra_) const { -+ C2_MacroAssembler _masm(&cbuf); ++void MachBreakpointNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { + __ brk(5); +} + @@ -28343,11 +29221,10 @@ index 00000000000..c725468b09f +} + +// Helper methods for MachSpillCopyNode::implementation(). -+static int vec_mov_helper(CodeBuffer *cbuf, bool do_size, int src_lo, int dst_lo, ++static int vec_mov_helper(C2_MacroAssembler *masm, bool do_size, int src_lo, int dst_lo, + int src_hi, int dst_hi, uint ireg, outputStream* st) { + int size = 0; -+ if (cbuf) { -+ MacroAssembler _masm(cbuf); ++ if (masm) { + int offset = __ offset(); + switch (ireg) { + case Op_VecS: @@ -28389,25 +29266,34 @@ index 00000000000..c725468b09f + return size; +} + -+static int vec_spill_helper(CodeBuffer *cbuf, bool do_size, bool is_load, ++static int vec_spill_helper(C2_MacroAssembler *masm, bool do_size, bool is_load, + int stack_offset, int reg, uint ireg, outputStream* st) { + int size = 0; -+ if (cbuf) { -+ MacroAssembler _masm(cbuf); ++ if (masm) { + int offset = __ offset(); + if (is_load) { + switch (ireg) { + case Op_VecS: -+ __ fld_s(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ __ fld_s(as_FloatRegister(Matcher::_regEncode[reg]), Address(SP, stack_offset)); + break; + case Op_VecD: -+ __ fld_d(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ __ fld_d(as_FloatRegister(Matcher::_regEncode[reg]), Address(SP, stack_offset)); + break; + case Op_VecX: -+ __ vld(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ if (Assembler::is_simm(stack_offset, 12)) { ++ __ vld(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ } else { ++ __ li(AT, stack_offset); ++ __ vldx(as_FloatRegister(Matcher::_regEncode[reg]), SP, AT); ++ } + break; + case Op_VecY: -+ __ xvld(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ if (Assembler::is_simm(stack_offset, 12)) { ++ __ xvld(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ } else { ++ __ li(AT, stack_offset); ++ __ xvldx(as_FloatRegister(Matcher::_regEncode[reg]), SP, AT); ++ } + break; + default: + ShouldNotReachHere(); @@ -28415,16 +29301,26 @@ index 00000000000..c725468b09f + } else { // store + switch (ireg) { + case Op_VecS: -+ __ fst_s(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ __ fst_s(as_FloatRegister(Matcher::_regEncode[reg]), Address(SP, stack_offset)); + break; + case Op_VecD: -+ __ fst_d(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ __ fst_d(as_FloatRegister(Matcher::_regEncode[reg]), Address(SP, stack_offset)); + break; + case Op_VecX: -+ __ vst(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ if (Assembler::is_simm(stack_offset, 12)) { ++ __ vst(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ } else { ++ __ li(AT, stack_offset); ++ __ vstx(as_FloatRegister(Matcher::_regEncode[reg]), SP, AT); ++ } + break; + case Op_VecY: -+ __ xvst(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ if (Assembler::is_simm(stack_offset, 12)) { ++ __ xvst(as_FloatRegister(Matcher::_regEncode[reg]), SP, stack_offset); ++ } else { ++ __ li(AT, stack_offset); ++ __ xvstx(as_FloatRegister(Matcher::_regEncode[reg]), SP, AT); ++ } + break; + default: + ShouldNotReachHere(); @@ -28473,11 +29369,10 @@ index 00000000000..c725468b09f + return size; +} + -+static int vec_stack_to_stack_helper(CodeBuffer *cbuf, int src_offset, ++static int vec_stack_to_stack_helper(C2_MacroAssembler *masm, int src_offset, + int dst_offset, uint ireg, outputStream* st) { + int size = 0; -+ if (cbuf) { -+ MacroAssembler _masm(cbuf); ++ if (masm) { + switch (ireg) { + case Op_VecS: + __ fld_s(F23, SP, src_offset); @@ -28530,7 +29425,7 @@ index 00000000000..c725468b09f + return size; +} + -+uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, PhaseRegAlloc *ra_, bool do_size, outputStream* st ) const { ++uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *ra_, bool do_size, outputStream* st) const { + // Get registers to move + OptoReg::Name src_second = ra_->get_reg_second(in(1)); + OptoReg::Name src_first = ra_->get_reg_first(in(1)); @@ -28556,15 +29451,15 @@ index 00000000000..c725468b09f + // mem -> mem + int src_offset = ra_->reg2offset(src_first); + int dst_offset = ra_->reg2offset(dst_first); -+ vec_stack_to_stack_helper(cbuf, src_offset, dst_offset, ireg, st); ++ vec_stack_to_stack_helper(masm, src_offset, dst_offset, ireg, st); + } else if (src_first_rc == rc_float && dst_first_rc == rc_float) { -+ vec_mov_helper(cbuf, do_size, src_first, dst_first, src_second, dst_second, ireg, st); ++ vec_mov_helper(masm, do_size, src_first, dst_first, src_second, dst_second, ireg, st); + } else if (src_first_rc == rc_float && dst_first_rc == rc_stack) { + int stack_offset = ra_->reg2offset(dst_first); -+ vec_spill_helper(cbuf, do_size, false, stack_offset, src_first, ireg, st); ++ vec_spill_helper(masm, do_size, false, stack_offset, src_first, ireg, st); + } else if (src_first_rc == rc_stack && dst_first_rc == rc_float) { + int stack_offset = ra_->reg2offset(src_first); -+ vec_spill_helper(cbuf, do_size, true, stack_offset, dst_first, ireg, st); ++ vec_spill_helper(masm, do_size, true, stack_offset, dst_first, ireg, st); + } else { + ShouldNotReachHere(); + } @@ -28581,8 +29476,7 @@ index 00000000000..c725468b09f + // 64-bit + int src_offset = ra_->reg2offset(src_first); + int dst_offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ ld_d(AT, Address(SP, src_offset)); + __ st_d(AT, Address(SP, dst_offset)); +#ifndef PRODUCT @@ -28599,8 +29493,7 @@ index 00000000000..c725468b09f + // No pushl/popl, so: + int src_offset = ra_->reg2offset(src_first); + int dst_offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ ld_w(AT, Address(SP, src_offset)); + __ st_w(AT, Address(SP, dst_offset)); +#ifndef PRODUCT @@ -28618,8 +29511,7 @@ index 00000000000..c725468b09f + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit + int offset = ra_->reg2offset(src_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ ld_d(as_Register(Matcher::_regEncode[dst_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28633,8 +29525,7 @@ index 00000000000..c725468b09f + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); + int offset = ra_->reg2offset(src_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + if (this->ideal_reg() == Op_RegI) + __ ld_w(as_Register(Matcher::_regEncode[dst_first]), Address(SP, offset)); + else { @@ -28660,8 +29551,7 @@ index 00000000000..c725468b09f + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit + int offset = ra_->reg2offset(src_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fld_d( as_FloatRegister(Matcher::_regEncode[dst_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28675,8 +29565,7 @@ index 00000000000..c725468b09f + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); + int offset = ra_->reg2offset(src_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fld_s( as_FloatRegister(Matcher::_regEncode[dst_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28696,8 +29585,7 @@ index 00000000000..c725468b09f + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit + int offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ st_d(as_Register(Matcher::_regEncode[src_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28711,8 +29599,7 @@ index 00000000000..c725468b09f + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); + int offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ st_w(as_Register(Matcher::_regEncode[src_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28727,8 +29614,7 @@ index 00000000000..c725468b09f + if ((src_first & 1) == 0 && src_first + 1 == src_second && + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ move(as_Register(Matcher::_regEncode[dst_first]), + as_Register(Matcher::_regEncode[src_first])); +#ifndef PRODUCT @@ -28743,8 +29629,7 @@ index 00000000000..c725468b09f + // 32-bit + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + if (this->ideal_reg() == Op_RegI) + __ move_u32(as_Register(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); + else @@ -28763,8 +29648,7 @@ index 00000000000..c725468b09f + if ((src_first & 1) == 0 && src_first + 1 == src_second && + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ movgr2fr_d(as_FloatRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28777,8 +29661,7 @@ index 00000000000..c725468b09f + // 32-bit + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ movgr2fr_w(as_FloatRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28798,8 +29681,7 @@ index 00000000000..c725468b09f + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit + int offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fst_d( as_FloatRegister(Matcher::_regEncode[src_first]), Address(SP, offset) ); +#ifndef PRODUCT + } else { @@ -28813,8 +29695,7 @@ index 00000000000..c725468b09f + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); + int offset = ra_->reg2offset(dst_first); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fst_s(as_FloatRegister(Matcher::_regEncode[src_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { @@ -28830,8 +29711,7 @@ index 00000000000..c725468b09f + if ((src_first & 1) == 0 && src_first + 1 == src_second && + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ movfr2gr_d( as_Register(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28844,8 +29724,7 @@ index 00000000000..c725468b09f + // 32-bit + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ movfr2gr_s( as_Register(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28861,8 +29740,7 @@ index 00000000000..c725468b09f + if ((src_first & 1) == 0 && src_first + 1 == src_second && + (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + // 64-bit -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fmov_d( as_FloatRegister(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28875,8 +29753,7 @@ index 00000000000..c725468b09f + // 32-bit + assert(!((src_first & 1) == 0 && src_first + 1 == src_second), "no transform"); + assert(!((dst_first & 1) == 0 && dst_first + 1 == dst_second), "no transform"); -+ if (cbuf) { -+ C2_MacroAssembler _masm(cbuf); ++ if (masm) { + __ fmov_s( as_FloatRegister(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { @@ -28901,8 +29778,8 @@ index 00000000000..c725468b09f +} +#endif + -+void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -+ implementation( &cbuf, ra_, false, nullptr ); ++void MachSpillCopyNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { ++ implementation(masm, ra_, false, nullptr); +} + +uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { @@ -28936,9 +29813,8 @@ index 00000000000..c725468b09f +} +#endif + -+void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { ++void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { + Compile *C = ra_->C; -+ C2_MacroAssembler _masm(&cbuf); + int framesize = C->output()->frame_size_in_bytes(); + + assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); @@ -28994,8 +29870,7 @@ index 00000000000..c725468b09f + return 3 * 4; +} + -+void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -+ C2_MacroAssembler _masm(&cbuf); ++void BoxLockNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); + int reg = ra_->get_encode(this); + @@ -29021,8 +29896,7 @@ index 00000000000..c725468b09f +} +#endif + -+void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { -+ C2_MacroAssembler _masm(&cbuf); ++void MachNopNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *) const { + int i = 0; + for(i = 0; i < _count; i++) + __ nop(); @@ -29040,25 +29914,23 @@ index 00000000000..c725468b09f +//============================================================================= +#ifndef PRODUCT +void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream* st ) const { -+ st->print_cr("load_klass(T4, T0)"); -+ st->print_cr("\tbeq(T4, iCache, L)"); ++ st->print_cr("# MachUEPNode"); ++ if (UseCompressedClassPointers) { ++ st->print_cr("\tld_wu AT, T0, oopDesc::klass_offset_in_bytes()"); ++ st->print_cr("\tld_wu T4, T1, CompiledICData::speculated_klass_offset()"); ++ } else { ++ st->print_cr("\tld_d AT, T0, oopDesc::klass_offset_in_bytes()"); ++ st->print_cr("\tld_d T4, T1, CompiledICData::speculated_klass_offset()"); ++ } ++ st->print_cr("\tbeq(AT, T4, ic_hit)"); + st->print_cr("\tjmp(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type)"); -+ st->print_cr(" L:"); ++ st->print_cr(" ic_hit:"); +} +#endif + + -+void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -+ C2_MacroAssembler _masm(&cbuf); -+ int ic_reg = Matcher::inline_cache_reg_encode(); -+ Label L; -+ Register receiver = T0; -+ Register iCache = as_Register(ic_reg); -+ -+ __ load_klass(T4, receiver); -+ __ beq(T4, iCache, L); -+ __ jmp((address)SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); -+ __ bind(L); ++void MachUEPNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { ++ __ ic_check(InteriorEntryAlignment); +} + +uint MachUEPNode::size(PhaseRegAlloc *ra_) const { @@ -29080,21 +29952,21 @@ index 00000000000..c725468b09f + ShouldNotReachHere(); +} + -+void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { ++void MachConstantBaseNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc* ra_) const { + Compile* C = ra_->C; + ConstantTable& constant_table = C->output()->constant_table(); -+ C2_MacroAssembler _masm(&cbuf); + + Register Rtoc = as_Register(ra_->get_encode(this)); -+ CodeSection* consts_section = cbuf.consts(); -+ int consts_size = cbuf.insts()->align_at_start(consts_section->size()); ++ CodeSection* consts_section = __ code()->consts(); ++ CodeSection* insts_section = __ code()->insts(); ++ int consts_size = insts_section->align_at_start(consts_section->size()); + assert(constant_table.size() == consts_size, "must be equal"); + + if (consts_section->size()) { + assert((CodeBuffer::SECT_CONSTS + 1) == CodeBuffer::SECT_INSTS, + "insts must be immediately follow consts"); + // Materialize the constant table base. -+ address baseaddr = cbuf.insts()->start() - consts_size + -(constant_table.table_base_offset()); ++ address baseaddr = insts_section->start() - consts_size + -(constant_table.table_base_offset()); + jint offs = (baseaddr - __ pc()) >> 2; + guarantee(Assembler::is_simm(offs, 20), "Not signed 20-bit offset"); + __ pcaddi(Rtoc, offs); @@ -29159,9 +30031,8 @@ index 00000000000..c725468b09f +#endif + + -+void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { ++void MachPrologNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc *ra_) const { + Compile* C = ra_->C; -+ C2_MacroAssembler _masm(&cbuf); + + int framesize = C->output()->frame_size_in_bytes(); + int bangsize = C->output()->bang_size_in_bytes(); @@ -29210,11 +30081,11 @@ index 00000000000..c725468b09f + guard = &stub->guard(); + } + // In the C2 code, we move the non-hot part of nmethod entry barriers out-of-line to a stub. -+ bs->nmethod_entry_barrier(&_masm, slow_path, continuation, guard); ++ bs->nmethod_entry_barrier(masm, slow_path, continuation, guard); + } + } + -+ C->output()->set_frame_complete(cbuf.insts_size()); ++ C->output()->set_frame_complete(__ offset()); + if (C->has_mach_constant_base_node()) { + // NOTE: We set the table base offset here because users might be + // emitted before MachConstantBaseNode. @@ -29401,28 +30272,23 @@ index 00000000000..c725468b09f +encode %{ + + enc_class Java_To_Runtime (method meth) %{ // CALL Java_To_Runtime, Java_To_Runtime_Leaf -+ C2_MacroAssembler _masm(&cbuf); + // This is the instruction starting address for relocation info. + __ block_comment("Java_To_Runtime"); -+ cbuf.set_insts_mark(); + __ relocate(relocInfo::runtime_call_type); + __ patchable_call((address)$meth$$method); -+ _masm.clear_inst_mark(); + __ post_call_nop(); + %} + + enc_class Java_Static_Call (method meth) %{ // JAVA STATIC CALL + // CALL to fixup routine. Fixup routine uses ScopeDesc info to determine + // who we intended to call. -+ C2_MacroAssembler _masm(&cbuf); -+ cbuf.set_insts_mark(); + address addr = (address)$meth$$method; + address call; + __ block_comment("Java_Static_Call"); + + if ( !_method ) { + // A call to a runtime wrapper, e.g. new, new_typeArray_Java, uncommon_trap. -+ call = __ trampoline_call(AddressLiteral(addr, relocInfo::runtime_call_type), &cbuf); ++ call = __ trampoline_call(AddressLiteral(addr, relocInfo::runtime_call_type)); + if (call == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); + return; @@ -29433,10 +30299,10 @@ index 00000000000..c725468b09f + __ nop(); + __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); + } else { -+ int method_index = resolved_method_index(cbuf); ++ int method_index = resolved_method_index(masm); + RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) + : static_call_Relocation::spec(method_index); -+ call = __ trampoline_call(AddressLiteral(addr, rspec), &cbuf); ++ call = __ trampoline_call(AddressLiteral(addr, rspec)); + if (call == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); + return; @@ -29444,17 +30310,16 @@ index 00000000000..c725468b09f + if (CodeBuffer::supports_shared_stubs() && _method->can_be_statically_bound()) { + // Calls of the same statically bound method can share + // a stub to the interpreter. -+ cbuf.shared_stub_to_interp_for(_method, cbuf.insts()->mark_off()); ++ __ code()->shared_stub_to_interp_for(_method, call - (__ begin())); + } else { + // Emit stub for static call -+ address stub = CompiledStaticCall::emit_to_interp_stub(cbuf); ++ address stub = CompiledDirectCall::emit_to_interp_stub(masm, call); + if (stub == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + } + } -+ _masm.clear_inst_mark(); + __ post_call_nop(); + %} + @@ -29463,14 +30328,12 @@ index 00000000000..c725468b09f + // [Ref: LIR_Assembler::ic_call() ] + // + enc_class Java_Dynamic_Call (method meth) %{ // JAVA DYNAMIC CALL -+ C2_MacroAssembler _masm(&cbuf); + __ block_comment("Java_Dynamic_Call"); -+ address call = __ ic_call((address)$meth$$method, resolved_method_index(cbuf)); ++ address call = __ ic_call((address)$meth$$method, resolved_method_index(masm)); + if (call == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } -+ _masm.clear_inst_mark(); + __ post_call_nop(); + %} + @@ -29489,7 +30352,6 @@ index 00000000000..c725468b09f + // 4bc mov S2, nullptr #@loadConP + // 4c0 beq S1, S2, B21 #@branchConP P=0.999999 C=-1.000000 + // -+ C2_MacroAssembler _masm(&cbuf); + Label done; + __ check_klass_subtype_slow_path(sub, super, length, tmp, + nullptr, &miss, @@ -29709,15 +30571,6 @@ index 00000000000..c725468b09f + interface(CONST_INTER); +%} + -+operand immIU1() %{ -+ predicate((0 <= n->get_int()) && (n->get_int() <= 1)); -+ match(ConI); -+ -+ op_cost(5); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ +operand immIU2() %{ + predicate((0 <= n->get_int()) && (n->get_int() <= 3)); + match(ConI); @@ -29828,33 +30681,6 @@ index 00000000000..c725468b09f + interface(CONST_INTER); +%} + -+operand immI_2() %{ -+ predicate(n->get_int() == 2); -+ match(ConI); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ -+operand immI_4() %{ -+ predicate(n->get_int() == 4); -+ match(ConI); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ -+operand immI_8() %{ -+ predicate(n->get_int() == 8); -+ match(ConI); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ +operand immI_16() %{ + predicate(n->get_int() == 16); + match(ConI); @@ -30035,17 +30861,6 @@ index 00000000000..c725468b09f + interface(CONST_INTER); +%} + -+// Long Immediate 32-bit signed -+operand immL32() -+%{ -+ predicate(n->get_long() == (int)n->get_long()); -+ match(ConL); -+ -+ op_cost(15); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ +// Long Immediate zero +operand immL_0() %{ + predicate(n->get_long() == 0L); @@ -30102,26 +30917,6 @@ index 00000000000..c725468b09f + interface(CONST_INTER); +%} + -+operand immL_gt_7() -+%{ -+ predicate(n->get_long() > 7); -+ match(ConL); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ -+operand immL_gt_15() -+%{ -+ predicate(n->get_long() > 15); -+ match(ConL); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ +// Pointer Immediate +operand immP() %{ + match(ConP); @@ -30245,79 +31040,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand mS0RegI() %{ -+ constraint(ALLOC_IN_RC(s0_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S0" %} -+ interface(REG_INTER); -+%} -+ -+operand mS1RegI() %{ -+ constraint(ALLOC_IN_RC(s1_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S1" %} -+ interface(REG_INTER); -+%} -+ -+operand mS3RegI() %{ -+ constraint(ALLOC_IN_RC(s3_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S3" %} -+ interface(REG_INTER); -+%} -+ -+operand mS4RegI() %{ -+ constraint(ALLOC_IN_RC(s4_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S4" %} -+ interface(REG_INTER); -+%} -+ -+operand mS5RegI() %{ -+ constraint(ALLOC_IN_RC(s5_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S5" %} -+ interface(REG_INTER); -+%} -+ -+operand mS6RegI() %{ -+ constraint(ALLOC_IN_RC(s6_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S6" %} -+ interface(REG_INTER); -+%} -+ -+operand mS7RegI() %{ -+ constraint(ALLOC_IN_RC(s7_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "S7" %} -+ interface(REG_INTER); -+%} -+ -+ -+operand mT0RegI() %{ -+ constraint(ALLOC_IN_RC(t0_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "T0" %} -+ interface(REG_INTER); -+%} -+ +operand mT1RegI() %{ + constraint(ALLOC_IN_RC(t1_reg)); + match(RegI); @@ -30336,15 +31058,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand mT3RegI() %{ -+ constraint(ALLOC_IN_RC(t3_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "T3" %} -+ interface(REG_INTER); -+%} -+ +operand mT8RegI() %{ + constraint(ALLOC_IN_RC(t8_reg)); + match(RegI); @@ -30354,15 +31067,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand mT4RegI() %{ -+ constraint(ALLOC_IN_RC(t4_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "T4" %} -+ interface(REG_INTER); -+%} -+ +operand mA0RegI() %{ + constraint(ALLOC_IN_RC(a0_reg)); + match(RegI); @@ -30390,15 +31094,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand mA3RegI() %{ -+ constraint(ALLOC_IN_RC(a3_reg)); -+ match(RegI); -+ match(mRegI); -+ -+ format %{ "A3" %} -+ interface(REG_INTER); -+%} -+ +operand mA4RegI() %{ + constraint(ALLOC_IN_RC(a4_reg)); + match(RegI); @@ -30443,186 +31138,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand t0_RegN() %{ -+ constraint(ALLOC_IN_RC(t0_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t1_RegN() %{ -+ constraint(ALLOC_IN_RC(t1_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t3_RegN() %{ -+ constraint(ALLOC_IN_RC(t3_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t8_RegN() %{ -+ constraint(ALLOC_IN_RC(t8_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a0_RegN() %{ -+ constraint(ALLOC_IN_RC(a0_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a1_RegN() %{ -+ constraint(ALLOC_IN_RC(a1_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a2_RegN() %{ -+ constraint(ALLOC_IN_RC(a2_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a3_RegN() %{ -+ constraint(ALLOC_IN_RC(a3_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a4_RegN() %{ -+ constraint(ALLOC_IN_RC(a4_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a5_RegN() %{ -+ constraint(ALLOC_IN_RC(a5_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a6_RegN() %{ -+ constraint(ALLOC_IN_RC(a6_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a7_RegN() %{ -+ constraint(ALLOC_IN_RC(a7_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s0_RegN() %{ -+ constraint(ALLOC_IN_RC(s0_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s1_RegN() %{ -+ constraint(ALLOC_IN_RC(s1_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s2_RegN() %{ -+ constraint(ALLOC_IN_RC(s2_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s3_RegN() %{ -+ constraint(ALLOC_IN_RC(s3_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s4_RegN() %{ -+ constraint(ALLOC_IN_RC(s4_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s5_RegN() %{ -+ constraint(ALLOC_IN_RC(s5_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s6_RegN() %{ -+ constraint(ALLOC_IN_RC(s6_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s7_RegN() %{ -+ constraint(ALLOC_IN_RC(s7_reg)); -+ match(RegN); -+ match(mRegN); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +// Pointer Register +operand mRegP() %{ + constraint(ALLOC_IN_RC(p_reg)); @@ -30643,8 +31158,10 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand p_has_s6_mRegP() %{ -+ constraint(ALLOC_IN_RC(p_has_s6_reg)); ++// This operand is not allowed to use FP even if ++// FP is not used to hold the frame pointer. ++operand no_FP_mRegP() %{ ++ constraint(ALLOC_IN_RC(no_FP_reg)); + match(RegP); + match(mRegP); + @@ -30652,13 +31169,12 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand s1_RegP() -+%{ -+ constraint(ALLOC_IN_RC(s1_long_reg)); ++operand p_has_s6_mRegP() %{ ++ constraint(ALLOC_IN_RC(p_has_s6_reg)); + match(RegP); + match(mRegP); + -+ format %{ %} ++ format %{ %} + interface(REG_INTER); +%} + @@ -30672,36 +31188,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand s4_RegP() -+%{ -+ constraint(ALLOC_IN_RC(s4_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s5_RegP() -+%{ -+ constraint(ALLOC_IN_RC(s5_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s6_RegP() -+%{ -+ constraint(ALLOC_IN_RC(s6_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +// Java Thread Register +operand javaThread_RegP(mRegP reg) +%{ @@ -30712,65 +31198,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand s7_RegP() -+%{ -+ constraint(ALLOC_IN_RC(s7_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t0_RegP() -+%{ -+ constraint(ALLOC_IN_RC(t0_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t1_RegP() -+%{ -+ constraint(ALLOC_IN_RC(t1_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t2_RegP() -+%{ -+ constraint(ALLOC_IN_RC(t2_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t3_RegP() -+%{ -+ constraint(ALLOC_IN_RC(t3_long_reg)); -+ match(RegP); -+ match(mRegP); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t8_RegP() -+%{ -+ constraint(ALLOC_IN_RC(t8_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +operand a0_RegP() +%{ + constraint(ALLOC_IN_RC(a0_long_reg)); @@ -30842,36 +31269,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand a7_RegP() -+%{ -+ constraint(ALLOC_IN_RC(a7_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand v0_RegP() -+%{ -+ constraint(ALLOC_IN_RC(v0_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand v1_RegP() -+%{ -+ constraint(ALLOC_IN_RC(v1_long_reg)); -+ match(RegP); -+ match(mRegP); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +operand mRegL() %{ + constraint(ALLOC_IN_RC(long_reg)); + match(RegL); @@ -30894,33 +31291,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand v0RegL() %{ -+ constraint(ALLOC_IN_RC(v0_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand v1RegL() %{ -+ constraint(ALLOC_IN_RC(v1_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a0RegL() %{ -+ constraint(ALLOC_IN_RC(a0_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ "A0" %} -+ interface(REG_INTER); -+%} -+ +operand a1RegL() %{ + constraint(ALLOC_IN_RC(a1_long_reg)); + match(RegL); @@ -30939,24 +31309,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand a3RegL() %{ -+ constraint(ALLOC_IN_RC(a3_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t0RegL() %{ -+ constraint(ALLOC_IN_RC(t0_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +operand t1RegL() %{ + constraint(ALLOC_IN_RC(t1_long_reg)); + match(RegL); @@ -30975,105 +31327,6 @@ index 00000000000..c725468b09f + interface(REG_INTER); +%} + -+operand t3RegL() %{ -+ constraint(ALLOC_IN_RC(t3_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand t8RegL() %{ -+ constraint(ALLOC_IN_RC(t8_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a4RegL() %{ -+ constraint(ALLOC_IN_RC(a4_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a5RegL() %{ -+ constraint(ALLOC_IN_RC(a5_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a6RegL() %{ -+ constraint(ALLOC_IN_RC(a6_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand a7RegL() %{ -+ constraint(ALLOC_IN_RC(a7_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s0RegL() %{ -+ constraint(ALLOC_IN_RC(s0_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s1RegL() %{ -+ constraint(ALLOC_IN_RC(s1_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s3RegL() %{ -+ constraint(ALLOC_IN_RC(s3_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s4RegL() %{ -+ constraint(ALLOC_IN_RC(s4_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand s7RegL() %{ -+ constraint(ALLOC_IN_RC(s7_long_reg)); -+ match(RegL); -+ match(mRegL); -+ -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +// Floating register operands +operand regF() %{ + constraint(ALLOC_IN_RC(flt_reg)); @@ -32379,7 +32632,9 @@ index 00000000000..c725468b09f +// Also known as an 'interprocedural jump'. +// Target of jump will eventually return to caller. +// TailJump below removes the return address. -+instruct TailCalljmpInd(mRegP jump_target, s3_RegP method_ptr) %{ ++// Don't use FP for 'jump_target' because a MachEpilogNode has already been ++// emitted just above the TailCall which has reset FP to the caller state. ++instruct TailCalljmpInd(no_FP_mRegP jump_target, s3_RegP method_ptr) %{ + match(TailCall jump_target method_ptr); + + format %{ "JMP $jump_target \t# @TailCalljmpInd" %} @@ -32445,8 +32700,7 @@ index 00000000000..c725468b09f + ins_encode %{ + __ block_comment("@ RethrowException"); + -+ cbuf.set_insts_mark(); -+ cbuf.relocate(cbuf.insts_mark(), runtime_call_Relocation::spec()); ++ __ relocate(runtime_call_Relocation::spec()); + + // call OptoRuntime::rethrow_stub to get the exception handler in parent method + __ patchable_jump((address)OptoRuntime::rethrow_stub()); @@ -35637,65 +35891,93 @@ index 00000000000..c725468b09f + ins_pipe( pipe_slow ); +%} + -+instruct string_compareL(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI result, mRegL tmp1, mRegL tmp2, regF vtmp1, regF vtmp2) %{ ++instruct string_compareL(a1_RegP str1, mA2RegI cnt1, a3_RegP str2, mA4RegI cnt2, ++ mA0RegI result, mRegL tmp1, mRegL tmp2, ++ regF vtmp1, regF vtmp2) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); -+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, ++ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ ++ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] " ++ "tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> " ++ "$result @ string_compareL" %} + -+ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> $result @ string_compareL" %} + ins_encode %{ -+ __ string_compare($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ StrIntrinsicNode::LL, $tmp1$$Register, $tmp2$$Register, -+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); ++ __ string_compareL($str1$$Register, $str2$$Register, ++ $cnt1$$Register, $cnt2$$Register, ++ $result$$Register, ++ $tmp1$$Register, $tmp2$$Register, ++ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); + %} + + ins_pipe( pipe_slow ); +%} + -+instruct string_compareU(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI result, mRegL tmp1, mRegL tmp2, regF vtmp1, regF vtmp2) %{ ++instruct string_compareU(a1_RegP str1, mA2RegI cnt1, a3_RegP str2, mA4RegI cnt2, ++ mA0RegI result, mRegL tmp1, mRegL tmp2, ++ regF vtmp1, regF vtmp2) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); -+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, ++ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ ++ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] " ++ "tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> " ++ "$result @ string_compareU" %} + -+ format %{ "String Compare char[] $str1[len: $cnt1], $str2[len: $cnt2] tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> $result @ string_compareU" %} + ins_encode %{ -+ __ string_compare($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ StrIntrinsicNode::UU, $tmp1$$Register, $tmp2$$Register, -+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); ++ __ string_compareU($str1$$Register, $str2$$Register, ++ $cnt1$$Register, $cnt2$$Register, ++ $result$$Register, ++ $tmp1$$Register, $tmp2$$Register, ++ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); + %} + + ins_pipe( pipe_slow ); +%} + -+instruct string_compareLU(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI result, mRegL tmp1, mRegL tmp2, regF vtmp1, regF vtmp2) %{ ++instruct string_compareLU(a1_RegP str1, mA2RegI cnt1, a3_RegP str2, mA4RegI cnt2, ++ mA0RegI result, mRegL tmp1, mRegL tmp2, ++ regF vtmp1, regF vtmp2) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); -+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, ++ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ ++ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] " ++ "tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> " ++ "$result @ string_compareLU" %} + -+ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> $result @ string_compareLU" %} + ins_encode %{ -+ __ string_compare($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ StrIntrinsicNode::LU, $tmp1$$Register, $tmp2$$Register, -+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); ++ __ string_compareLU($str1$$Register, $str2$$Register, ++ $cnt1$$Register, $cnt2$$Register, ++ $result$$Register, ++ $tmp1$$Register, $tmp2$$Register, ++ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); + %} + + ins_pipe( pipe_slow ); +%} + -+instruct string_compareUL(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI result, mRegL tmp1, mRegL tmp2, regF vtmp1, regF vtmp2) %{ ++instruct string_compareUL(a1_RegP str1, mA2RegI cnt1, a3_RegP str2, mA4RegI cnt2, ++ mA0RegI result, mRegL tmp1, mRegL tmp2, ++ regF vtmp1, regF vtmp2) %{ + predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); -+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP vtmp1, TEMP vtmp2, ++ USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2); ++ ++ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] " ++ "tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> " ++ "$result @ string_compareUL" %} + -+ format %{ "String Compare byte[] $str1[len: $cnt1], $str2[len: $cnt2] tmp1:$tmp1, tmp2:$tmp2, vtmp1:$vtmp1, vtmp2:$vtmp2 -> $result @ string_compareUL" %} + ins_encode %{ -+ __ string_compare($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ StrIntrinsicNode::UL, $tmp1$$Register, $tmp2$$Register, -+ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); ++ __ string_compareUL($str1$$Register, $str2$$Register, ++ $cnt1$$Register, $cnt2$$Register, ++ $result$$Register, ++ $tmp1$$Register, $tmp2$$Register, ++ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); + %} + + ins_pipe( pipe_slow ); @@ -35983,6 +36265,25 @@ index 00000000000..c725468b09f + ins_pipe( pipe_slow ); +%} + ++// fast ArraysSupport.vectorizedHashCode ++instruct arrays_hashcode(a1_RegP ary, mA2RegI cnt, mA0RegI result, immI basic_type, ++ mRegL tmp1, mRegL tmp2, mRegL tmp3, mRegL tmp4, ++ mRegL tmp5, mRegL tmp6, mRegL tmp7) ++%{ ++ match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type))); ++ effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6, TEMP tmp7, ++ USE_KILL ary, USE_KILL cnt, USE basic_type); ++ ++ format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result @ arrays_hashcode" %} ++ ins_encode %{ ++ __ arrays_hashcode($ary$$Register, $cnt$$Register, $result$$Register, ++ $tmp1$$Register, $tmp2$$Register, $tmp3$$Register, ++ $tmp4$$Register, $tmp5$$Register, $tmp6$$Register, ++ $tmp7$$Register, (BasicType)$basic_type$$constant); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +//----------Arithmetic Instructions------------------------------------------- +//----------Addition Instructions--------------------------------------------- +instruct addI_Reg_Reg(mRegI dst, mRegIorL2I src1, mRegIorL2I src2) %{ @@ -38191,7 +38492,7 @@ index 00000000000..c725468b09f +// "restore" before this instruction (in Epilogue), we need to materialize it +// in %i0. +//FIXME -+instruct tailjmpInd(mRegP jump_target, a0_RegP ex_oop, mA1RegI exception_pc) %{ ++instruct tailjmpInd(no_FP_mRegP jump_target, a0_RegP ex_oop, mA1RegI exception_pc) %{ + match( TailJump jump_target ex_oop ); + ins_cost(200); + format %{ "Jmp $jump_target ; ex_oop = $ex_oop #@tailjmpInd" %} @@ -38624,6 +38925,7 @@ index 00000000000..c725468b09f +%} + +instruct cmpFastLock(FlagsReg cr, no_CR_mRegP object, no_CR_mRegP box, no_CR_mRegP tmp1, no_CR_mRegP tmp2) %{ ++ predicate(LockingMode != LM_LIGHTWEIGHT); + match(Set cr (FastLock object box)); + effect(TEMP tmp1, TEMP tmp2); + @@ -38637,6 +38939,7 @@ index 00000000000..c725468b09f +%} + +instruct cmpFastUnlock(FlagsReg cr, no_CR_mRegP object, no_CR_mRegP box, no_CR_mRegP tmp1, no_CR_mRegP tmp2) %{ ++ predicate(LockingMode != LM_LIGHTWEIGHT); + match(Set cr (FastUnlock object box)); + effect(TEMP tmp1, TEMP tmp2); + @@ -38649,6 +38952,34 @@ index 00000000000..c725468b09f + ins_pipe( pipe_slow ); +%} + ++instruct cmpFastLockLightweight(FlagsReg cr, no_CR_mRegP object, no_CR_mRegP box, no_CR_mRegP tmp1, no_CR_mRegP tmp2, no_CR_mRegP tmp3) %{ ++ predicate(LockingMode == LM_LIGHTWEIGHT); ++ match(Set cr (FastLock object box)); ++ effect(TEMP tmp1, TEMP tmp2, TEMP tmp3); ++ ++ format %{ "FASTLOCK $cr <-- $object, $box, $tmp1, $tmp2, $tmp3 #@ cmpFastLockLightweight" %} ++ ++ ins_encode %{ ++ __ fast_lock_lightweight($object$$Register, $cr$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); ++ %} ++ ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct cmpFastUnlockLightweight(FlagsReg cr, no_CR_mRegP object, no_CR_mRegP box, no_CR_mRegP tmp1, no_CR_mRegP tmp2, no_CR_mRegP tmp3) %{ ++ predicate(LockingMode == LM_LIGHTWEIGHT); ++ match(Set cr (FastUnlock object box)); ++ effect(TEMP tmp1, TEMP tmp2, TEMP tmp3); ++ ++ format %{ "FASTUNLOCK $cr <-- $object, $box, $tmp1, $tmp2, $tmp3 #@ cmpFastUnlockLightweight" %} ++ ++ ins_encode %{ ++ __ fast_unlock_lightweight($object$$Register, $cr$$Register, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); ++ %} ++ ++ ins_pipe( pipe_slow ); ++%} ++ +// Store card-mark Immediate 0 +instruct storeImmCM(memory mem, immI_0 zero) %{ + match(Set mem (StoreCM mem zero)); @@ -42850,6 +43181,39 @@ index 00000000000..c725468b09f + ins_pipe(pipe_slow); +%} + ++// ------------------------------ ReverseBytesV -------------------------------- ++ ++instruct reverseBytesV(vReg dst, vReg src) %{ ++ match(Set dst (ReverseBytesV src)); ++ format %{ "(x)vreverse_byte $dst, $src\t# @reverseBytesV" %} ++ ins_encode %{ ++ if (Matcher::vector_length_in_bytes(this) > 16) { ++ switch (Matcher::vector_element_basic_type(this)) { ++ case T_BYTE : if ($dst$$FloatRegister != $src$$FloatRegister) ++ __ xvori_b($dst$$FloatRegister, $src$$FloatRegister, 0); break; ++ case T_SHORT : __ xvshuf4i_b($dst$$FloatRegister, $src$$FloatRegister, 0b10110001); break; ++ case T_INT : __ xvshuf4i_b($dst$$FloatRegister, $src$$FloatRegister, 0b00011011); break; ++ case T_LONG : __ xvshuf4i_w($dst$$FloatRegister, $src$$FloatRegister, 0b10110001); ++ __ xvshuf4i_b($dst$$FloatRegister, $dst$$FloatRegister, 0b00011011); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ } else { ++ switch (Matcher::vector_element_basic_type(this)) { ++ case T_BYTE : if ($dst$$FloatRegister != $src$$FloatRegister) ++ __ vori_b($dst$$FloatRegister, $src$$FloatRegister, 0); break; ++ case T_SHORT : __ vshuf4i_b($dst$$FloatRegister, $src$$FloatRegister, 0b10110001); break; ++ case T_INT : __ vshuf4i_b($dst$$FloatRegister, $src$$FloatRegister, 0b00011011); break; ++ case T_LONG : __ vshuf4i_w($dst$$FloatRegister, $src$$FloatRegister, 0b10110001); ++ __ vshuf4i_b($dst$$FloatRegister, $dst$$FloatRegister, 0b00011011); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ } ++ %} ++ ins_pipe(pipe_slow); ++%} ++ + +//----------PEEPHOLE RULES----------------------------------------------------- +// These must follow all instruction definitions as they use the names @@ -42954,13 +43318,13 @@ index 00000000000..c725468b09f + diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp new file mode 100644 -index 00000000000..1e23abc76f8 +index 00000000000..3b47dfbef59 --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp -@@ -0,0 +1,4279 @@ +@@ -0,0 +1,4345 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2017, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2017, 2024, Loongson Technology. 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 @@ -42987,6 +43351,7 @@ index 00000000000..1e23abc76f8 +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "asm/macroAssembler.inline.hpp" ++#include "code/compiledIC.hpp" +#include "compiler/disassembler.hpp" +#include "compiler/oopMap.hpp" +#include "gc/shared/barrierSet.hpp" @@ -43010,6 +43375,7 @@ index 00000000000..1e23abc76f8 +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" ++#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +#ifdef COMPILER2 @@ -43123,7 +43489,7 @@ index 00000000000..1e23abc76f8 + +// Maybe emit a call via a trampoline. If the code cache is small +// trampolines won't be emitted. -+address MacroAssembler::trampoline_call(AddressLiteral entry, CodeBuffer* cbuf) { ++address MacroAssembler::trampoline_call(AddressLiteral entry) { + assert(entry.rspec().type() == relocInfo::runtime_call_type || + entry.rspec().type() == relocInfo::opt_virtual_call_type || + entry.rspec().type() == relocInfo::static_call_type || @@ -43143,13 +43509,12 @@ index 00000000000..1e23abc76f8 + target = pc(); + } + -+ if (cbuf != nullptr) { cbuf->set_insts_mark(); } ++ address call_pc = pc(); + relocate(entry.rspec()); + bl(target); + -+ // just need to return a non-null address + postcond(pc() != badAddress); -+ return pc(); ++ return call_pc; +} + +// Emit a trampoline stub for a call to a target which is too far away. @@ -43558,6 +43923,41 @@ index 00000000000..1e23abc76f8 + return trampoline_call(AddressLiteral(entry, rh)); +} + ++int MacroAssembler::ic_check_size() { ++ return 4 * 5; ++} ++ ++int MacroAssembler::ic_check(int end_alignment) { ++ Register receiver = j_rarg0; ++ Register data = IC_Klass; ++ Register tmp1 = SCR1; ++ Register tmp2 = SCR2; ++ ++ // The UEP of a code blob ensures that the VEP is padded. However, the padding of the UEP is placed ++ // before the inline cache check, so we don't have to execute any nop instructions when dispatching ++ // through the UEP, yet we can ensure that the VEP is aligned appropriately. That's why we align ++ // before the inline cache check here, and not after ++ align(end_alignment, offset() + ic_check_size()); ++ int uep_offset = offset(); ++ ++ if (UseCompressedClassPointers) { ++ ld_wu(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); ++ ld_wu(tmp2, Address(data, CompiledICData::speculated_klass_offset())); ++ } else { ++ ld_d(tmp1, Address(receiver, oopDesc::klass_offset_in_bytes())); ++ ld_d(tmp2, Address(data, CompiledICData::speculated_klass_offset())); ++ } ++ ++ Label ic_hit; ++ beq(tmp1, tmp2, ic_hit); ++ relocate(relocInfo::runtime_call_type); ++ patchable_jump(SharedRuntime::get_ic_miss_stub(), true /* force patchable */); ++ bind(ic_hit); ++ ++ assert((offset() % end_alignment) == 0, "Misaligned verified entry point."); ++ return uep_offset; ++} ++ +void MacroAssembler::emit_static_call_stub() { + // Code stream for loading method may be changed. + ibar(0); @@ -43980,7 +44380,7 @@ index 00000000000..1e23abc76f8 + // we may safely use the sp instead to perform the stack watermark check. + blt_far(AT, in_nmethod ? SP : FP, slow_path, false /* signed */); + } else { -+ andi(AT, AT, SafepointMechanism::poll_bit()); ++ test_bit(AT, AT, exact_log2(SafepointMechanism::poll_bit())); + bnez(AT, slow_path); + } +} @@ -44056,23 +44456,6 @@ index 00000000000..1e23abc76f8 + bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); +} + -+void MacroAssembler::incr_allocated_bytes(Register thread, -+ Register var_size_in_bytes, -+ int con_size_in_bytes, -+ Register t1) { -+ if (!thread->is_valid()) { -+ thread = TREG; -+ } -+ -+ ld_d(AT, Address(thread, JavaThread::allocated_bytes_offset())); -+ if (var_size_in_bytes->is_valid()) { -+ add_d(AT, AT, var_size_in_bytes); -+ } else { -+ addi_d(AT, AT, con_size_in_bytes); -+ } -+ st_d(AT, Address(thread, JavaThread::allocated_bytes_offset())); -+} -+ +void MacroAssembler::li(Register rd, jlong value) { + jlong hi12 = bitfield(value, 52, 12); + jlong lo52 = bitfield(value, 0, 52); @@ -44305,6 +44688,10 @@ index 00000000000..1e23abc76f8 + slli_w(dst, dst, 0); // keep sign, clear upper bits +} + ++void MacroAssembler::test_bit(Register dst, Register src, uint32_t bit_pos) { ++ bstrpick_d(dst, src, bit_pos, bit_pos); ++} ++ +void MacroAssembler::cmpxchg(Address addr, Register oldval, Register newval, + Register resflag, bool retold, bool acquire, + bool weak, bool exchange) { @@ -44734,7 +45121,14 @@ index 00000000000..1e23abc76f8 +} + +void MacroAssembler::align(int modulus) { -+ while (offset() % modulus != 0) nop(); ++ align(modulus, offset()); ++} ++ ++// Ensure that the code at target bytes offset from the current offset() is aligned ++// according to modulus. ++void MacroAssembler::align(int modulus, int target) { ++ int delta = target - offset(); ++ while ((offset() + delta) % modulus != 0) nop(); +} + +void MacroAssembler::post_call_nop() { @@ -45624,7 +46018,7 @@ index 00000000000..1e23abc76f8 + + ld_w(scan_temp, Address(recv_klass, Klass::vtable_length_offset())); + -+ // %%% Could store the aligned, prescaled offset in the klassoop. ++ // Could store the aligned, prescaled offset in the klass. + alsl_d(scan_temp, scan_temp, recv_klass, times_vte_scale - 1); + addi_d(scan_temp, scan_temp, vtable_base); + @@ -45703,7 +46097,7 @@ index 00000000000..1e23abc76f8 + + bind(tagged); + // Test for jweak tag. -+ andi(AT, value, JNIHandles::TypeTag::weak_global); ++ test_bit(AT, value, exact_log2(JNIHandles::TypeTag::weak_global)); + bnez(AT, weak_tagged); + + // Resolve global handle @@ -45729,7 +46123,7 @@ index 00000000000..1e23abc76f8 +#ifdef ASSERT + { + Label valid_global_tag; -+ andi(AT, value, JNIHandles::TypeTag::global); // Test for global tag. ++ test_bit(AT, value, exact_log2(JNIHandles::TypeTag::global)); + bnez(AT, valid_global_tag); + stop("non global jobject using resolve_global_jobject"); + bind(valid_global_tag); @@ -46283,12 +46677,16 @@ index 00000000000..1e23abc76f8 + address prev = pc() - NativeInstruction::sync_instruction_size; + address last = code()->last_insn(); + if (last != nullptr && ((NativeInstruction*)last)->is_sync() && prev == last) { -+ code()->set_last_insn(nullptr); + NativeMembar *membar = (NativeMembar*)prev; ++#ifndef PRODUCT ++ char buf[50]; ++ snprintf(buf, sizeof(buf), "merged membar 0x%x 0x%x => 0x%x", ++ (Ordering | membar->get_hint()), (Ordering | (~hint & 0xF)), (Ordering | (membar->get_hint() & (~hint & 0xF)))); ++ block_comment(buf); ++#endif + // merged membar + // e.g. LoadLoad and LoadLoad|LoadStore to LoadLoad|LoadStore + membar->set_hint(membar->get_hint() & (~hint & 0xF)); -+ block_comment("merged membar"); + } else { + code()->set_last_insn(pc()); + Assembler::membar(hint); @@ -47093,97 +47491,129 @@ index 00000000000..1e23abc76f8 +} + +// Implements lightweight-locking. -+// Branches to slow upon failure to lock the object. -+// Falls through upon success. +// +// - obj: the object to be locked -+// - hdr: the header, already loaded from obj, will be destroyed -+// - flag: as cr for c2, but only as temporary regisgter for c1/interpreter -+// - tmp: temporary registers, will be destroyed -+void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { ++// - tmp1, tmp2, tmp3: temporary registers, will be destroyed ++// - slow: branched to if locking fails ++void MacroAssembler::lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) { + assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking"); -+ assert_different_registers(obj, hdr, flag, tmp); -+ -+ // Check if we would have space on lock-stack for the object. -+ ld_wu(flag, Address(TREG, JavaThread::lock_stack_top_offset())); -+ li(tmp, (unsigned)LockStack::end_offset()); -+ sltu(flag, flag, tmp); -+ beqz(flag, slow); -+ -+ // Load (object->mark() | 1) into hdr -+ ori(hdr, hdr, markWord::unlocked_value); -+ // Clear lock-bits, into tmp -+ xori(tmp, hdr, markWord::unlocked_value); -+ // Try to swing header from unlocked to locked -+ cmpxchg(/*addr*/ Address(obj, 0), /*old*/ hdr, /*new*/ tmp, /*flag*/ flag, /*retold*/ true, /*barrier*/true); -+ beqz(flag, slow); -+ -+ // After successful lock, push object on lock-stack -+ ld_wu(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); -+ stx_d(obj, TREG, tmp); -+ addi_w(tmp, tmp, oopSize); -+ st_w(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); ++ assert_different_registers(obj, tmp1, tmp2, tmp3); ++ ++ Label _push, _tmp; ++ const Register top = tmp1; ++ const Register mark = tmp2; ++ const Register t = tmp3; ++ ++ // Preload the markWord. It is important that this is the first ++ // instruction emitted as it is part of C1's null check semantics. ++ ld_d(mark, Address(obj, oopDesc::mark_offset_in_bytes())); ++ ++ // Check if the lock-stack is full. ++ ld_wu(top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ li(t, (unsigned)LockStack::end_offset()); ++ blt(top, t, _tmp); ++ b(slow); ++ bind(_tmp); ++ ++ // Check for recursion. ++ add_d(t, TREG, top); ++ ld_d(t, t, -oopSize); ++ beq(obj, t, _push); ++ ++ // Check header for monitor (0b10). ++ test_bit(t, mark, exact_log2(markWord::monitor_value)); ++ bnez(t, slow); ++ ++ // Try to lock. Transition lock-bits 0b01 => 0b00 ++ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid a lea"); ++ ori(mark, mark, markWord::unlocked_value); ++ xori(t, mark, markWord::unlocked_value); ++ push(top); ++ cmpxchg(Address(obj, 0), mark, t, top, true, true /*acquire*/); ++ move(t, top); ++ pop(top); ++ beqz(t, slow); ++ ++ bind(_push); ++ // After successful lock, push object on lock-stack. ++ stx_d(obj, TREG, top); ++ addi_w(top, top, oopSize); ++ st_w(top, Address(TREG, JavaThread::lock_stack_top_offset())); +} + +// Implements lightweight-unlocking. -+// Branches to slow upon failure. -+// Falls through upon success. +// +// - obj: the object to be unlocked -+// - hdr: the (pre-loaded) header of the object -+// - flag: as cr for c2, but only as temporary regisgter for c1/interpreter -+// - tmp: temporary registers -+void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { ++// - tmp1, tmp2, tmp3: temporary registers ++// - slow: branched to if unlocking fails ++void MacroAssembler::lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow) { + assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking"); -+ assert_different_registers(obj, hdr, tmp, flag); ++ assert_different_registers(obj, tmp1, tmp2, tmp3); + +#ifdef ASSERT + { -+ // The following checks rely on the fact that LockStack is only ever modified by -+ // its owning thread, even if the lock got inflated concurrently; removal of LockStack -+ // entries after inflation will happen delayed in that case. -+ + // Check for lock-stack underflow. + Label stack_ok; -+ ld_wu(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); -+ li(flag, (unsigned)LockStack::start_offset()); -+ bltu(flag, tmp, stack_ok); ++ ld_wu(tmp1, Address(TREG, JavaThread::lock_stack_top_offset())); ++ li(tmp2, (unsigned)LockStack::start_offset()); ++ bge(tmp1, tmp2, stack_ok); + stop("Lock-stack underflow"); + bind(stack_ok); + } -+ { -+ // Check if the top of the lock-stack matches the unlocked object. -+ Label tos_ok; -+ addi_w(tmp, tmp, -oopSize); -+ ldx_d(tmp, TREG, tmp); -+ beq(tmp, obj, tos_ok); -+ stop("Top of lock-stack does not match the unlocked object"); -+ bind(tos_ok); -+ } -+ { -+ // Check that hdr is fast-locked. -+ Label hdr_ok; -+ andi(tmp, hdr, markWord::lock_mask_in_place); -+ beqz(tmp, hdr_ok); -+ stop("Header is not fast-locked"); -+ bind(hdr_ok); -+ } +#endif + -+ // Load the new header (unlocked) into tmp -+ ori(tmp, hdr, markWord::unlocked_value); ++ Label unlocked, push_and_slow; ++ const Register top = tmp1; ++ const Register mark = tmp2; ++ const Register t = tmp3; ++ ++ // Check if obj is top of lock-stack. ++ ld_wu(top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ addi_w(top, top, -oopSize); ++ ldx_d(t, TREG, top); ++ sub_d(t, obj, t); ++ bnez(t, slow); ++ ++ // Pop lock-stack. ++ DEBUG_ONLY(stx_d(R0, TREG, top);) ++ st_w(top, Address(TREG, JavaThread::lock_stack_top_offset())); + -+ // Try to swing header from locked to unlocked -+ cmpxchg(/*addr*/ Address(obj, 0), /*old*/ hdr, /*new*/ tmp, /*flag*/ flag, /**/true, /*barrier*/ true); -+ beqz(flag, slow); ++ // Check if recursive. ++ add_d(t, TREG, top); ++ ld_d(t, t, -oopSize); ++ beq(obj, t, unlocked); ++ ++ // Not recursive. Check header for monitor (0b10). ++ ld_d(mark, Address(obj, oopDesc::mark_offset_in_bytes())); ++ test_bit(t, mark, exact_log2(markWord::monitor_value)); ++ bnez(t, push_and_slow); + -+ // After successful unlock, pop object from lock-stack -+ ld_wu(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); -+ addi_w(tmp, tmp, -oopSize); +#ifdef ASSERT -+ stx_d(R0, TREG, tmp); ++ // Check header not unlocked (0b01). ++ Label not_unlocked; ++ test_bit(t, mark, exact_log2(markWord::unlocked_value)); ++ beqz(t, not_unlocked); ++ stop("lightweight_unlock already unlocked"); ++ bind(not_unlocked); +#endif -+ st_w(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); ++ ++ // Try to unlock. Transition lock bits 0b00 => 0b01 ++ assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea"); ++ ori(t, mark, markWord::unlocked_value); ++ push(top); ++ cmpxchg(Address(obj, 0), mark, t, top, true, false /*acquire*/); ++ move(t, top); ++ pop(top); ++ bnez(t, unlocked); ++ ++ bind(push_and_slow); ++ // Restore lock-stack and handle the unlock in runtime. ++ DEBUG_ONLY(stx_d(obj, TREG, top);) ++ addi_w(top, top, oopSize); ++ st_w(top, Address(TREG, JavaThread::lock_stack_top_offset())); ++ b(slow); ++ ++ bind(unlocked); +} + +#if INCLUDE_ZGC @@ -47239,13 +47669,13 @@ index 00000000000..1e23abc76f8 +#endif diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp new file mode 100644 -index 00000000000..dbed82cd653 +index 00000000000..22797f0ebb4 --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp -@@ -0,0 +1,815 @@ +@@ -0,0 +1,819 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -47387,6 +47817,7 @@ index 00000000000..dbed82cd653 + + // Alignment + void align(int modulus); ++ void align(int modulus, int target); + + void post_call_nop(); + @@ -47583,9 +48014,6 @@ index 00000000000..dbed82cd653 + Register t2, // temp register + Label& slow_case // continuation point if fast allocation fails + ); -+ void incr_allocated_bytes(Register thread, -+ Register var_size_in_bytes, int con_size_in_bytes, -+ Register t1 = noreg); + // interface method calling + void lookup_interface_method(Register recv_klass, + Register intf_klass, @@ -47723,7 +48151,8 @@ index 00000000000..dbed82cd653 + void call(address entry, RelocationHolder& rh); + void call_long(address entry); + -+ address trampoline_call(AddressLiteral entry, CodeBuffer *cbuf = nullptr); ++ // Return: the call PC or null if CodeCache is full. ++ address trampoline_call(AddressLiteral entry); + + static const unsigned long branch_range = NOT_DEBUG(128 * M) DEBUG_ONLY(2 * M); + @@ -47737,6 +48166,8 @@ index 00000000000..dbed82cd653 + + // Emit the CompiledIC call idiom + address ic_call(address entry, jint method_index = 0); ++ static int ic_check_size(); ++ int ic_check(int end_alignment); + + void emit_static_call_stub(); + @@ -47789,6 +48220,9 @@ index 00000000000..dbed82cd653 + // convert big endian integer to little endian integer + void bswap_w(Register dst, Register src); + ++ // test single bit in src, result is set to dst ++ void test_bit(Register dst, Register src, uint32_t bit_pos); ++ + void cmpxchg(Address addr, Register oldval, Register newval, Register resflag, + bool retold, bool acquire, bool weak = false, bool exchange = false); + void cmpxchg(Address addr, Register oldval, Register newval, Register tmp, @@ -47992,8 +48426,8 @@ index 00000000000..dbed82cd653 + } + } + -+ void lightweight_lock(Register obj, Register hdr, Register flag, Register tmp, Label& slow); -+ void lightweight_unlock(Register obj, Register hdr, Register flag, Register tmp, Label& slow); ++ void lightweight_lock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow); ++ void lightweight_unlock(Register obj, Register tmp1, Register tmp2, Register tmp3, Label& slow); + +#if INCLUDE_ZGC + void patchable_li16(Register rd, uint16_t value); @@ -49095,13 +49529,13 @@ index 00000000000..ea4d5a2ac4c +} diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp new file mode 100644 -index 00000000000..b4a1b09b375 +index 00000000000..0c31904a36b --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp -@@ -0,0 +1,1625 @@ +@@ -0,0 +1,1626 @@ +/* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT) -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -49995,7 +50429,7 @@ index 00000000000..b4a1b09b375 + b(Q_DONE); + bind(JX_IS_0); + if (UseLASX) { -+ xvfmul_d(v28, v18, v6); // f[0,1] * x[0] ++ xvfmul_d(v28, v18, v6); // f[0,3] * x[0] + fmul_d(v30, v19, v6); // f[4] * x[0] + } else { + vfmul_d(v28, v18, v6); // f[0,1] * x[0] @@ -50229,6 +50663,7 @@ index 00000000000..b4a1b09b375 + st_w(tmp2, SCR2, 0); + addi_w(SCR1, SCR1, 24); + addi_w(jz, jz, 1); ++ alsl_d(SCR2, jz, iqBase, 2 - 1); + st_w(tmp3, SCR2, 0); // iq[jz] = (int) fw + b(Z_ZERO_CHECK_DONE); + bind(Z_IS_LESS_THAN_TWO24B); @@ -50726,13 +51161,13 @@ index 00000000000..b4a1b09b375 +} diff --git a/src/hotspot/cpu/loongarch/matcher_loongarch.hpp b/src/hotspot/cpu/loongarch/matcher_loongarch.hpp new file mode 100644 -index 00000000000..012e781dba8 +index 00000000000..766d05b9403 --- /dev/null +++ b/src/hotspot/cpu/loongarch/matcher_loongarch.hpp -@@ -0,0 +1,181 @@ +@@ -0,0 +1,191 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -50850,6 +51285,11 @@ index 00000000000..012e781dba8 + return true; + } + ++ // Does target support predicated operation emulation. ++ static bool supports_vector_predicate_op_emulation(int vopc, int vlen, BasicType bt) { ++ return false; ++ } ++ + // Does the CPU supports vector variable rotate instructions? + static constexpr bool supports_vector_variable_rotates(void) { + return true; @@ -50910,6 +51350,11 @@ index 00000000000..012e781dba8 + } + } + ++ // Is SIMD sort supported for this CPU? ++ static bool supports_simd_sort(BasicType bt) { ++ return false; ++ } ++ +#endif // CPU_LOONGARCH_MATCHER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp b/src/hotspot/cpu/loongarch/methodHandles_loongarch.cpp new file mode 100644 @@ -51558,13 +52003,13 @@ index 00000000000..8e129225509 + } diff --git a/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp b/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp new file mode 100644 -index 00000000000..c298cda5de7 +index 00000000000..c67984e5c2f --- /dev/null +++ b/src/hotspot/cpu/loongarch/nativeInst_loongarch.cpp -@@ -0,0 +1,537 @@ +@@ -0,0 +1,546 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -51630,6 +52075,10 @@ index 00000000000..c298cda5de7 + Assembler::high(int_at(4), 7) == Assembler::lu32i_d_op; +} + ++bool NativeInstruction::is_pcaddi() const { ++ return Assembler::high(int_at(0), 7) == Assembler::pcaddi_op; ++} ++ +bool NativeInstruction::is_pcaddu12i_add() const { + return Assembler::high(int_at(0), 7) == Assembler::pcaddu12i_op && + Assembler::high(int_at(4), 10) == Assembler::addi_d_op; @@ -52075,12 +52524,16 @@ index 00000000000..c298cda5de7 + NativeDeoptInstruction::insert(addr_at(0)); +} + -+void NativePostCallNop::patch(jint diff) { -+ assert(diff != 0, "must be"); ++bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { ++ if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { ++ return false; // cannot encode ++ } ++ uint32_t data = ((uint32_t)oopmap_slot << 24) | cb_offset; ++ assert(data != 0, "must be"); + assert(check(), "must be"); + -+ int lo = (diff & 0xffff); -+ int hi = ((diff >> 16) & 0xffff); ++ int lo = (data & 0xffff); ++ int hi = ((data >> 16) & 0xffff); + + uint32_t *code_pos_first = (uint32_t *) addr_at(4); + uint32_t *code_pos_second = (uint32_t *) addr_at(8); @@ -52089,6 +52542,7 @@ index 00000000000..c298cda5de7 + + *((uint32_t *)(code_pos_first)) = (uint32_t) ((opcode | lo) << 5); + *((uint32_t *)(code_pos_second)) = (uint32_t) ((opcode | hi) << 5); ++ return true; // successfully encoded +} + +void NativeDeoptInstruction::verify() { @@ -52101,13 +52555,13 @@ index 00000000000..c298cda5de7 +} diff --git a/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp b/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp new file mode 100644 -index 00000000000..3a322a218a3 +index 00000000000..e8fc94a1f58 --- /dev/null +++ b/src/hotspot/cpu/loongarch/nativeInst_loongarch.hpp -@@ -0,0 +1,595 @@ +@@ -0,0 +1,602 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -52182,6 +52636,7 @@ index 00000000000..3a322a218a3 + // Helper func for jvmci + bool is_lu12iw_lu32id() const; + bool is_pcaddu12i_add() const; ++ bool is_pcaddi() const; + + // LoongArch has no instruction to generate a illegal instruction exception? + // But `break 11` is not illegal instruction for LoongArch. @@ -52643,15 +53098,21 @@ index 00000000000..3a322a218a3 + return is_nop() && ((uint_at(4) & 0xffc0001f) == 0x03800000); + } + -+ jint displacement() const { ++ bool decode(int32_t& oopmap_slot, int32_t& cb_offset) const { + uint32_t first_ori = uint_at(4); + uint32_t second_ori = uint_at(8); + int lo = ((first_ori >> 5) & 0xffff); + int hi = ((second_ori >> 5) & 0xffff); -+ return (jint) ((hi << 16) | lo); ++ uint32_t data = (hi << 16) | lo; ++ if (data == 0) { ++ return false; // no information encoded ++ } ++ cb_offset = (data & 0xffffff); ++ oopmap_slot = (data >> 24) & 0xff; ++ return true; // decoding succeeded + } + -+ void patch(jint diff); ++ bool patch(int32_t oopmap_slot, int32_t cb_offset); + void make_deopt(); +}; + @@ -52834,13 +53295,13 @@ index 00000000000..5378fce5cd2 +} diff --git a/src/hotspot/cpu/loongarch/register_loongarch.hpp b/src/hotspot/cpu/loongarch/register_loongarch.hpp new file mode 100644 -index 00000000000..6ffdd41a5e7 +index 00000000000..e6f27f03ff8 --- /dev/null +++ b/src/hotspot/cpu/loongarch/register_loongarch.hpp @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -53306,26 +53767,26 @@ index 00000000000..6ffdd41a5e7 + +template <> +inline Register AbstractRegSet::first() { -+ uint32_t first = _bitset & -_bitset; -+ return first ? as_Register(exact_log2(first)) : noreg; ++ if (_bitset == 0) { return noreg; } ++ return as_Register(count_trailing_zeros(_bitset)); +} + +template <> +inline FloatRegister AbstractRegSet::first() { -+ uint32_t first = _bitset & -_bitset; -+ return first ? as_FloatRegister(exact_log2(first)) : fnoreg; ++ if (_bitset == 0) { return fnoreg; } ++ return as_FloatRegister(count_trailing_zeros(_bitset)); +} + +#endif //CPU_LOONGARCH_REGISTER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp b/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp new file mode 100644 -index 00000000000..d7011d57525 +index 00000000000..c190c221bac --- /dev/null +++ b/src/hotspot/cpu/loongarch/relocInfo_loongarch.cpp -@@ -0,0 +1,133 @@ +@@ -0,0 +1,132 @@ +/* + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -53359,8 +53820,7 @@ index 00000000000..d7011d57525 +#include "runtime/safepoint.hpp" + + -+void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { -+ x += o; ++void Relocation::pd_set_data_value(address x, bool verify_only) { + typedef Assembler::WhichOperand WhichOperand; + WhichOperand which = (WhichOperand) format(); // that is, disp32 or imm, call32, narrow oop + assert(which == Assembler::disp32_operand || @@ -53508,10 +53968,10 @@ index 00000000000..c85ca4963f3 +#endif // CPU_LOONGARCH_RELOCINFO_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp b/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp new file mode 100644 -index 00000000000..23763cc6c78 +index 00000000000..e83b221a5b1 --- /dev/null +++ b/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp -@@ -0,0 +1,2977 @@ +@@ -0,0 +1,2996 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Loongson Technology. All rights reserved. @@ -53542,13 +54002,11 @@ index 00000000000..23763cc6c78 +#include "asm/macroAssembler.inline.hpp" +#include "code/compiledIC.hpp" +#include "code/debugInfoRec.hpp" -+#include "code/icBuffer.hpp" +#include "code/nativeInst.hpp" +#include "code/vtableStubs.hpp" +#include "compiler/oopMap.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "interpreter/interpreter.hpp" -+#include "oops/compiledICHolder.hpp" +#include "oops/klass.inline.hpp" +#include "oops/method.inline.hpp" +#include "prims/methodHandles.hpp" @@ -54206,25 +54664,18 @@ index 00000000000..23763cc6c78 + Label skip_fixup; + { + __ block_comment("c2i_unverified_entry {"); -+ Register holder = IC_Klass; ++ Register data = IC_Klass; + Register receiver = T0; + Register temp = T8; + address ic_miss = SharedRuntime::get_ic_miss_stub(); + -+ Label missed; -+ -+ //add for compressedoops -+ __ load_klass(temp, receiver); -+ -+ __ ld_d(AT, Address(holder, CompiledICHolder::holder_klass_offset())); -+ __ ld_d(Rmethod, Address(holder, CompiledICHolder::holder_metadata_offset())); -+ __ bne(AT, temp, missed); + // Method might have been compiled since the call site was patched to + // interpreted if that is the case treat it as a miss so we can get + // the call site corrected. ++ __ ic_check(1 /* end_alignment */); ++ __ ld_d(Rmethod, Address(data, CompiledICData::speculated_method_offset())); + __ ld_d(AT, Address(Rmethod, Method::code_offset())); + __ beq(AT, R0, skip_fixup); -+ __ bind(missed); + + __ jmp(ic_miss, relocInfo::runtime_call_type); + __ block_comment("} c2i_unverified_entry"); @@ -54239,7 +54690,7 @@ index 00000000000..23763cc6c78 + + { // Bypass the barrier for non-static methods + __ ld_w(AT, Address(Rmethod, Method::access_flags_offset())); -+ __ andi(AT, AT, JVM_ACC_STATIC); ++ __ test_bit(AT, AT, exact_log2(JVM_ACC_STATIC)); + __ beqz(AT, L_skip_barrier); // non-static + } + @@ -54518,6 +54969,47 @@ index 00000000000..23763cc6c78 + + __ ld_d(AT, Address(SP, ContinuationEntry::parent_cont_fastpath_offset())); + __ st_d(AT, Address(TREG, JavaThread::cont_fastpath_offset())); ++ ++ if (CheckJNICalls) { ++ // Check if this is a virtual thread continuation ++ Label L_skip_vthread_code; ++ __ ld_wu(AT, Address(SP, ContinuationEntry::flags_offset())); ++ __ beqz(AT, 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_d(AT, Address(TREG, JavaThread::jni_monitor_count_offset())); ++ __ beqz(AT, L_skip_vthread_code); ++ ++ // Save return value potentially containing the exception oop in callee-saved TSR ++ __ move(TSR, A0); ++ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held)); ++ // Restore potential return value ++ __ move(A0, TSR); ++ ++ // 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). ++ __ st_d(R0, Address(TREG, 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; ++ __ ld_wu(AT, Address(SP, ContinuationEntry::flags_offset())); ++ __ beqz(AT, L_skip_vthread_code); ++ ++ // See comment just above. If not checking JNI calls the JNI count is only ++ // needed for assertion checking. ++ __ st_d(R0, Address(TREG, JavaThread::jni_monitor_count_offset())); ++ ++ __ bind(L_skip_vthread_code); ++ } ++#endif ++ + __ ld_d(AT, Address(SP, ContinuationEntry::parent_held_monitor_count_offset())); + __ st_d(AT, Address(TREG, JavaThread::held_monitor_count_offset())); + @@ -54585,8 +55077,7 @@ index 00000000000..23763cc6c78 + + __ b(exit); + -+ CodeBuffer* cbuf = masm->code_section()->outer(); -+ CompiledStaticCall::emit_to_interp_stub(*cbuf, mark); ++ CompiledDirectCall::emit_to_interp_stub(masm, mark); + } + + // compiled entry @@ -54650,8 +55141,7 @@ index 00000000000..23763cc6c78 + __ jr(T4); + } + -+ CodeBuffer* cbuf = masm->code_section()->outer(); -+ CompiledStaticCall::emit_to_interp_stub(*cbuf, mark); ++ CompiledDirectCall::emit_to_interp_stub(masm, mark); +} + +static void gen_continuation_yield(MacroAssembler* masm, @@ -54838,6 +55328,7 @@ index 00000000000..23763cc6c78 + in_ByteSize(-1), + oop_maps, + exception_offset); ++ if (nm == nullptr) return nm; + if (method->is_continuation_enter_intrinsic()) { + ContinuationEntry::set_enter_code(nm, interpreted_entry_offset); + } else if (method->is_continuation_yield_intrinsic()) { @@ -54998,24 +55489,17 @@ index 00000000000..23763cc6c78 + + + // First thing make an ic check to see if we should even be here -+ address ic_miss = SharedRuntime::get_ic_miss_stub(); + + // We are free to use all registers as temps without saving them and + // restoring them except fp. fp is the only callee save register + // as far as the interpreter and the compiler(s) are concerned. + -+ const Register ic_reg = IC_Klass; + const Register receiver = T0; + -+ Label hit; + Label exception_pending; + + __ verify_oop(receiver); -+ //add for compressedoops -+ __ load_klass(T4, receiver); -+ __ beq(T4, ic_reg, hit); -+ __ jmp(ic_miss, relocInfo::runtime_call_type); -+ __ bind(hit); ++ __ ic_check(8 /* end_alignment */); + + int vep_offset = ((intptr_t)__ pc()) - start; + @@ -55275,7 +55759,6 @@ index 00000000000..23763cc6c78 + __ bne(swap_reg, R0, slow_path_lock); + } else { + assert(LockingMode == LM_LIGHTWEIGHT, "must be"); -+ __ ld_d(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + // FIXME + Register tmp = T1; + __ lightweight_lock(obj_reg, swap_reg, tmp, SCR1, slow_path_lock); @@ -55438,9 +55921,6 @@ index 00000000000..23763cc6c78 + __ decrement(Address(TREG, JavaThread::held_monitor_count_offset()), 1); + } else { + assert(LockingMode == LM_LIGHTWEIGHT, ""); -+ __ ld_d(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); -+ __ andi(AT, lock_reg, markWord::monitor_value); -+ __ bnez(AT, slow_path_unlock); + __ lightweight_unlock(obj_reg, lock_reg, swap_reg, SCR1, slow_path_unlock); + __ decrement(Address(TREG, JavaThread::held_monitor_count_offset())); + } @@ -55988,15 +56468,12 @@ index 00000000000..23763cc6c78 +} + +#ifdef COMPILER2 -+ +//------------------------------generate_uncommon_trap_blob-------------------- -+// Ought to generate an ideal graph & compile, but here's some SPARC ASM -+// instead. +void SharedRuntime::generate_uncommon_trap_blob() { -+ // allocate space for the code ++ // Allocate space for the code + ResourceMark rm; -+ // setup code generation tools -+ CodeBuffer buffer ("uncommon_trap_blob", 512*80 , 512*40 ); ++ // Setup code generation tools ++ CodeBuffer buffer("uncommon_trap_blob", 2048, 1024); + MacroAssembler* masm = new MacroAssembler(&buffer); + + enum frame_layout { @@ -56005,40 +56482,51 @@ index 00000000000..23763cc6c78 + framesize + }; + assert(framesize % 4 == 0, "sp not 16-byte aligned"); ++ + address start = __ pc(); + + // Push self-frame. + __ addi_d(SP, SP, -framesize * BytesPerInt); -+ + __ st_d(RA, SP, return_off * BytesPerInt); + __ st_d(FP, SP, fp_off * BytesPerInt); ++ // we don't expect an arg reg save area ++#ifndef PRODUCT ++ assert(frame::arg_reg_save_area_bytes == 0, "not expecting frame reg save area"); ++#endif ++ // compiler left unloaded_class_index in j_rarg0 move to where the ++ // runtime expects it. ++ __ addi_w(c_rarg1, j_rarg0, 0); + -+ __ addi_d(FP, SP, framesize * BytesPerInt); -+ -+ // set last_Java_sp ++ // we need to set the past SP to the stack pointer of the stub frame ++ // and the pc to the address where this runtime call will return ++ // although actually any pc in this code blob will do). + Label retaddr; -+ __ set_last_Java_frame(NOREG, FP, retaddr); -+ // Call C code. Need thread but NOT official VM entry -+ // crud. We cannot block on this call, no GC can happen. Call should -+ // capture callee-saved registers as well as return values. -+ __ move(A0, TREG); -+ // argument already in T0 -+ __ move(A1, T0); -+ __ addi_d(A2, R0, Deoptimization::Unpack_uncommon_trap); -+ __ call((address)Deoptimization::uncommon_trap, relocInfo::runtime_call_type); ++ __ set_last_Java_frame(noreg, noreg, retaddr); ++ ++ // Call C code. We cannot block on this call, no GC can happen. ++ // Call should capture callee-saved registers as well as return values. ++ // ++ // UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode) ++ // ++ __ move(c_rarg0, TREG); ++ __ addi_w(c_rarg2, R0, (unsigned)Deoptimization::Unpack_uncommon_trap); ++ __ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), ++ relocInfo::runtime_call_type); + __ bind(retaddr); + + // Set an oopmap for the call site + OopMapSet *oop_maps = new OopMapSet(); -+ OopMap* map = new OopMap( framesize, 0 ); + -+ oop_maps->add_gc_map(__ pc() - start, map); ++ oop_maps->add_gc_map(__ pc() - start, new OopMap(framesize, 0)); + + __ reset_last_Java_frame(false); + -+ // Load UnrollBlock into S7 -+ Register unroll = S7; -+ __ move(unroll, V0); ++ Register unroll = T8; ++ Register pcs = T6; ++ Register sizes = T5; ++ Register count = T4; ++ ++ __ move(unroll, c_rarg0); // move call return value to unroll + +#ifdef ASSERT + { Label L; @@ -56055,107 +56543,98 @@ index 00000000000..23763cc6c78 + // Frame picture (youngest to oldest) + // 1: self-frame (no frame link) + // 2: deopting frame (no frame link) -+ // 3: possible-i2c-adapter-frame -+ // 4: caller of deopting frame (could be compiled/interpreted. If interpreted we will create an -+ // and c2i here) ++ // 3: caller of deopting frame (could be compiled/interpreted). + -+ __ addi_d(SP, SP, framesize * BytesPerInt); ++ __ addi_d(SP, SP, framesize << LogBytesPerInt); + -+ // Pop deoptimized frame -+ __ ld_w(T8, Address(unroll, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); -+ __ add_d(SP, SP, T8); ++ // Pop deoptimized frame (int) ++ __ ld_wu(AT, Address(unroll, Deoptimization::UnrollBlock::size_of_deoptimized_frame_offset())); ++ __ add_d(SP, SP, AT); ++ // LoongArch do not need to restore RA and FP here, since: ++ // 1: The RA shall be loaded by frame PC array (frame_pcs) later ++ // 2: The FP is protected via frame::initial_deoptimization_info() + +#ifdef ASSERT + // Compilers generate code that bang the stack by as much as the + // interpreter would need. So this stack banging should never + // trigger a fault. Verify that it does not on non product builds. -+ __ ld_w(TSR, Address(unroll, Deoptimization::UnrollBlock::total_frame_sizes_offset())); -+ __ bang_stack_size(TSR, T8); ++ __ ld_wu(sizes, Address(unroll, Deoptimization::UnrollBlock::total_frame_sizes_offset())); ++ __ bang_stack_size(sizes, pcs /* tmp */); +#endif + -+ // register for frame pcs -+ Register pcs = T8; -+ // register for frame sizes -+ Register sizes = T4; -+ // register for frame count -+ Register count = T3; -+ // register for the sender's sp -+ Register sender_sp = T1; -+ -+ // sp should be pointing at the return address to the caller (4) -+ // Load array of frame pcs + __ ld_d(pcs, Address(unroll, Deoptimization::UnrollBlock::frame_pcs_offset())); -+ -+ // Load array of frame sizes + __ ld_d(sizes, Address(unroll, Deoptimization::UnrollBlock::frame_sizes_offset())); + __ ld_wu(count, Address(unroll, Deoptimization::UnrollBlock::number_of_frames_offset())); + + // Pick up the initial fp we should save + __ ld_d(FP, Address(unroll, Deoptimization::UnrollBlock::initial_info_offset())); + -+ // Now adjust the caller's stack to make up for the extra locals -+ // but record the original sp so that we can save it in the skeletal interpreter -+ // frame and the stack walking of interpreter_sender will get the unextended sp -+ // value and not the "real" sp value. -+ __ move(sender_sp, SP); -+ __ ld_w(AT, Address(unroll, Deoptimization::UnrollBlock::caller_adjustment_offset())); ++ // Now adjust the caller's stack to make up for the extra locals but ++ // record the original sp so that we can save it in the skeletal ++ // interpreter frame and the stack walking of interpreter_sender ++ // will get the unextended sp value and not the "real" sp value. ++ ++ __ move(Rsender, SP); ++ __ ld_wu(AT, Address(unroll, Deoptimization::UnrollBlock::caller_adjustment_offset())); + __ sub_d(SP, SP, AT); + + // Push interpreter frames in a loop + Label loop; + __ bind(loop); -+ __ ld_d(T2, sizes, 0); // Load frame size -+ __ ld_d(RA, pcs, 0); // save return address -+ __ addi_d(T2, T2, -2*wordSize); // we'll push pc and fp, by hand ++ __ ld_d(AT, sizes, 0); // load frame size ++ __ ld_d(RA, pcs, 0); // save return address ++ __ addi_d(AT, AT, -2 * wordSize); // we'll push RA and FP, by hand + __ enter(); -+ __ sub_d(SP, SP, T2); // Prolog! ++ __ sub_d(SP, SP, AT); ++ // Save Rsender to make it walkable, and then pass it to next frame. ++ __ st_d(Rsender, FP, frame::interpreter_frame_sender_sp_offset * wordSize); ++ __ move(Rsender, SP); + // This value is corrected by layout_activation_impl + __ st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); -+ __ st_d(sender_sp, FP, frame::interpreter_frame_sender_sp_offset * wordSize);// Make it walkable -+ __ move(sender_sp, SP); // pass to next frame -+ __ addi_d(count, count, -1); // decrement counter -+ __ addi_d(sizes, sizes, wordSize); // Bump array pointer (sizes) -+ __ addi_d(pcs, pcs, wordSize); // Bump array pointer (pcs) -+ __ bne(count, R0, loop); ++ __ addi_d(count, count, -1); ++ __ addi_d(sizes, sizes, wordSize); ++ __ addi_d(pcs, pcs, wordSize); ++ __ blt(R0, count, loop); + -+ __ ld_d(RA, pcs, 0); ++ __ ld_d(RA, pcs, 0); // save final return address + -+ // Re-push self-frame -+ // save old & set new FP -+ // save final return address + __ enter(); + -+ // Use FP because the frames look interpreted now -+ // Save "the_pc" since it cannot easily be retrieved using the last_java_SP after we aligned SP. -+ // Don't need the precise return PC here, just precise enough to point into this code blob. ++ // Use FP because the frames look interpreted now. Save "the_pc" since it ++ // cannot easily be retrieved using the last_java_SP after we aligned SP. ++ // Do not need the precise return PC address here, just precise enough to ++ // point into this code blob. + Label L; + address the_pc = __ pc(); + __ bind(L); -+ __ set_last_Java_frame(NOREG, FP, L); ++ __ set_last_Java_frame(SP, FP, L); + + assert(StackAlignmentInBytes == 16, "must be"); -+ __ bstrins_d(SP, R0, 3, 0); // Fix stack alignment as required by ABI ++ __ bstrins_d(SP, R0, 3, 0); ++ ++ // Call C code. We cannot block on this call, no GC can happen. ++ // Call should capture callee-saved registers as well as return values. ++ // ++ // BasicType unpack_frames(JavaThread* thread, int exec_mode) ++ // ++ __ move(c_rarg0, TREG); ++ __ addi_w(c_rarg1, R0, (unsigned)Deoptimization::Unpack_uncommon_trap); ++ __ call(CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), ++ relocInfo::runtime_call_type); + -+ // Call C code. Need thread but NOT official VM entry -+ // crud. We cannot block on this call, no GC can happen. Call should -+ // restore return values to their stack-slots with the new SP. -+ __ move(A0, TREG); -+ __ li(A1, Deoptimization::Unpack_uncommon_trap); -+ __ call((address)Deoptimization::unpack_frames, relocInfo::runtime_call_type); + // Set an oopmap for the call site ++ // Use the same PC we used for the last java frame + oop_maps->add_gc_map(the_pc - start, new OopMap(framesize, 0)); + + __ reset_last_Java_frame(true); + -+ // Pop self-frame. -+ __ leave(); // Epilog! -+ -+ // Jump to interpreter ++ __ leave(); + __ jr(RA); -+ // ------------- ++ + // make sure all code is generated + masm->flush(); -+ _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, framesize / 2); ++ ++ _uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps, framesize >> 1); +} + +#endif // COMPILER2 @@ -56589,13 +57068,13 @@ index 00000000000..ebd11807b24 +#endif // CPU_LOONGARCH_SMALLREGISTERMAP_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/stackChunkFrameStream_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/stackChunkFrameStream_loongarch.inline.hpp new file mode 100644 -index 00000000000..5034e2924cb +index 00000000000..b40078d2955 --- /dev/null +++ b/src/hotspot/cpu/loongarch/stackChunkFrameStream_loongarch.inline.hpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -56630,7 +57109,7 @@ index 00000000000..5034e2924cb +inline bool StackChunkFrameStream::is_in_frame(void* p0) const { + assert(!is_done(), ""); + intptr_t* p = (intptr_t*)p0; -+ int argsize = is_compiled() ? (_cb->as_compiled_method()->method()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0; ++ int argsize = is_compiled() ? (_cb->as_nmethod()->num_stack_arg_slots() * VMRegImpl::stack_slot_size) >> LogBytesPerWord : 0; + int frame_size = _cb->frame_size() + argsize; + return p == sp() - 2 || ((p - unextended_sp()) >= 0 && (p - unextended_sp()) < frame_size); +} @@ -56786,13 +57265,13 @@ index 00000000000..3e6b0e2a5cb +#endif // CPU_LOONGARCH_STACKCHUNKOOP_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp b/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp new file mode 100644 -index 00000000000..f9b95b56af8 +index 00000000000..14f9640dae4 --- /dev/null +++ b/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp -@@ -0,0 +1,5952 @@ +@@ -0,0 +1,6462 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -57355,7 +57834,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le32, le16, le8, lt8; + + __ bind(entry); @@ -57458,7 +57937,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le64, le32, le16, lt16; + + __ bind(entry); @@ -57551,7 +58030,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le128, le64, le32, lt32; + + __ bind(entry); @@ -57641,7 +58120,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le32, le16, le8, lt8; + + __ bind(entry); @@ -57741,7 +58220,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le64, le32, le16, lt16; + + __ bind(entry); @@ -57831,7 +58310,7 @@ index 00000000000..f9b95b56af8 + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + Label loop, le128, le64, le32, lt32; + + __ bind(entry); @@ -58887,7 +59366,7 @@ index 00000000000..f9b95b56af8 + __ jr(RA); + + { -+ UnsafeCopyMemoryMark ucmm(this, true, true); ++ UnsafeMemoryAccessMark umam(this, true, true); + // 1: + __ bind(L1); + bs->copy_load_at(_masm, decorators, type, 8, T8, Address(A0, 0), gct1); @@ -60652,6 +61131,512 @@ index 00000000000..f9b95b56af8 + // Arguments: + // + // Inputs: ++ // A0 - source byte array address ++ // A1 - destination byte array address ++ // A2 - K (key) in little endian byte array ++ // ++ // Output: ++ // A0 - input length ++ // ++ void generate_descrypt_Block(address &entry_enc, address &entry_dec) { ++ static const uint32_t initPerm[] = { ++ 0x00000000, 0x00008000, 0x00000000, 0x00008000, 0x00000080, ++ 0x00008080, 0x00000080, 0x00008080, 0x00000000, 0x00008000, ++ 0x00000000, 0x00008000, 0x00000080, 0x00008080, 0x00000080, ++ 0x00008080, ++ 0x00000000, 0x80000000, 0x00000000, 0x80000000, 0x00800000, ++ 0x80800000, 0x00800000, 0x80800000, 0x00000000, 0x80000000, ++ 0x00000000, 0x80000000, 0x00800000, 0x80800000, 0x00800000, ++ 0x80800000, ++ 0x00000000, 0x00004000, 0x00000000, 0x00004000, 0x00000040, ++ 0x00004040, 0x00000040, 0x00004040, 0x00000000, 0x00004000, ++ 0x00000000, 0x00004000, 0x00000040, 0x00004040, 0x00000040, ++ 0x00004040, ++ 0x00000000, 0x40000000, 0x00000000, 0x40000000, 0x00400000, ++ 0x40400000, 0x00400000, 0x40400000, 0x00000000, 0x40000000, ++ 0x00000000, 0x40000000, 0x00400000, 0x40400000, 0x00400000, ++ 0x40400000, ++ 0x00000000, 0x00002000, 0x00000000, 0x00002000, 0x00000020, ++ 0x00002020, 0x00000020, 0x00002020, 0x00000000, 0x00002000, ++ 0x00000000, 0x00002000, 0x00000020, 0x00002020, 0x00000020, ++ 0x00002020, ++ 0x00000000, 0x20000000, 0x00000000, 0x20000000, 0x00200000, ++ 0x20200000, 0x00200000, 0x20200000, 0x00000000, 0x20000000, ++ 0x00000000, 0x20000000, 0x00200000, 0x20200000, 0x00200000, ++ 0x20200000, ++ 0x00000000, 0x00001000, 0x00000000, 0x00001000, 0x00000010, ++ 0x00001010, 0x00000010, 0x00001010, 0x00000000, 0x00001000, ++ 0x00000000, 0x00001000, 0x00000010, 0x00001010, 0x00000010, ++ 0x00001010, ++ 0x00000000, 0x10000000, 0x00000000, 0x10000000, 0x00100000, ++ 0x10100000, 0x00100000, 0x10100000, 0x00000000, 0x10000000, ++ 0x00000000, 0x10000000, 0x00100000, 0x10100000, 0x00100000, ++ 0x10100000, ++ 0x00000000, 0x00000800, 0x00000000, 0x00000800, 0x00000008, ++ 0x00000808, 0x00000008, 0x00000808, 0x00000000, 0x00000800, ++ 0x00000000, 0x00000800, 0x00000008, 0x00000808, 0x00000008, ++ 0x00000808, ++ 0x00000000, 0x08000000, 0x00000000, 0x08000000, 0x00080000, ++ 0x08080000, 0x00080000, 0x08080000, 0x00000000, 0x08000000, ++ 0x00000000, 0x08000000, 0x00080000, 0x08080000, 0x00080000, ++ 0x08080000, ++ 0x00000000, 0x00000400, 0x00000000, 0x00000400, 0x00000004, ++ 0x00000404, 0x00000004, 0x00000404, 0x00000000, 0x00000400, ++ 0x00000000, 0x00000400, 0x00000004, 0x00000404, 0x00000004, ++ 0x00000404, ++ 0x00000000, 0x04000000, 0x00000000, 0x04000000, 0x00040000, ++ 0x04040000, 0x00040000, 0x04040000, 0x00000000, 0x04000000, ++ 0x00000000, 0x04000000, 0x00040000, 0x04040000, 0x00040000, ++ 0x04040000, ++ 0x00000000, 0x00000200, 0x00000000, 0x00000200, 0x00000002, ++ 0x00000202, 0x00000002, 0x00000202, 0x00000000, 0x00000200, ++ 0x00000000, 0x00000200, 0x00000002, 0x00000202, 0x00000002, ++ 0x00000202, ++ 0x00000000, 0x02000000, 0x00000000, 0x02000000, 0x00020000, ++ 0x02020000, 0x00020000, 0x02020000, 0x00000000, 0x02000000, ++ 0x00000000, 0x02000000, 0x00020000, 0x02020000, 0x00020000, ++ 0x02020000, ++ 0x00000000, 0x00000100, 0x00000000, 0x00000100, 0x00000001, ++ 0x00000101, 0x00000001, 0x00000101, 0x00000000, 0x00000100, ++ 0x00000000, 0x00000100, 0x00000001, 0x00000101, 0x00000001, ++ 0x00000101, ++ 0x00000000, 0x01000000, 0x00000000, 0x01000000, 0x00010000, ++ 0x01010000, 0x00010000, 0x01010000, 0x00000000, 0x01000000, ++ 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00010000, ++ 0x01010000, ++ 0x00000000, 0x00000000, 0x00008000, 0x00008000, 0x00000000, ++ 0x00000000, 0x00008000, 0x00008000, 0x00000080, 0x00000080, ++ 0x00008080, 0x00008080, 0x00000080, 0x00000080, 0x00008080, ++ 0x00008080, ++ 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x00000000, ++ 0x00000000, 0x80000000, 0x80000000, 0x00800000, 0x00800000, ++ 0x80800000, 0x80800000, 0x00800000, 0x00800000, 0x80800000, ++ 0x80800000, ++ 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00000000, ++ 0x00000000, 0x00004000, 0x00004000, 0x00000040, 0x00000040, ++ 0x00004040, 0x00004040, 0x00000040, 0x00000040, 0x00004040, ++ 0x00004040, ++ 0x00000000, 0x00000000, 0x40000000, 0x40000000, 0x00000000, ++ 0x00000000, 0x40000000, 0x40000000, 0x00400000, 0x00400000, ++ 0x40400000, 0x40400000, 0x00400000, 0x00400000, 0x40400000, ++ 0x40400000, ++ 0x00000000, 0x00000000, 0x00002000, 0x00002000, 0x00000000, ++ 0x00000000, 0x00002000, 0x00002000, 0x00000020, 0x00000020, ++ 0x00002020, 0x00002020, 0x00000020, 0x00000020, 0x00002020, ++ 0x00002020, ++ 0x00000000, 0x00000000, 0x20000000, 0x20000000, 0x00000000, ++ 0x00000000, 0x20000000, 0x20000000, 0x00200000, 0x00200000, ++ 0x20200000, 0x20200000, 0x00200000, 0x00200000, 0x20200000, ++ 0x20200000, ++ 0x00000000, 0x00000000, 0x00001000, 0x00001000, 0x00000000, ++ 0x00000000, 0x00001000, 0x00001000, 0x00000010, 0x00000010, ++ 0x00001010, 0x00001010, 0x00000010, 0x00000010, 0x00001010, ++ 0x00001010, ++ 0x00000000, 0x00000000, 0x10000000, 0x10000000, 0x00000000, ++ 0x00000000, 0x10000000, 0x10000000, 0x00100000, 0x00100000, ++ 0x10100000, 0x10100000, 0x00100000, 0x00100000, 0x10100000, ++ 0x10100000, ++ 0x00000000, 0x00000000, 0x00000800, 0x00000800, 0x00000000, ++ 0x00000000, 0x00000800, 0x00000800, 0x00000008, 0x00000008, ++ 0x00000808, 0x00000808, 0x00000008, 0x00000008, 0x00000808, ++ 0x00000808, ++ 0x00000000, 0x00000000, 0x08000000, 0x08000000, 0x00000000, ++ 0x00000000, 0x08000000, 0x08000000, 0x00080000, 0x00080000, ++ 0x08080000, 0x08080000, 0x00080000, 0x00080000, 0x08080000, ++ 0x08080000, ++ 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000000, ++ 0x00000000, 0x00000400, 0x00000400, 0x00000004, 0x00000004, ++ 0x00000404, 0x00000404, 0x00000004, 0x00000004, 0x00000404, ++ 0x00000404, ++ 0x00000000, 0x00000000, 0x04000000, 0x04000000, 0x00000000, ++ 0x00000000, 0x04000000, 0x04000000, 0x00040000, 0x00040000, ++ 0x04040000, 0x04040000, 0x00040000, 0x00040000, 0x04040000, ++ 0x04040000, ++ 0x00000000, 0x00000000, 0x00000200, 0x00000200, 0x00000000, ++ 0x00000000, 0x00000200, 0x00000200, 0x00000002, 0x00000002, ++ 0x00000202, 0x00000202, 0x00000002, 0x00000002, 0x00000202, ++ 0x00000202, ++ 0x00000000, 0x00000000, 0x02000000, 0x02000000, 0x00000000, ++ 0x00000000, 0x02000000, 0x02000000, 0x00020000, 0x00020000, ++ 0x02020000, 0x02020000, 0x00020000, 0x00020000, 0x02020000, ++ 0x02020000, ++ 0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00000000, ++ 0x00000000, 0x00000100, 0x00000100, 0x00000001, 0x00000001, ++ 0x00000101, 0x00000101, 0x00000001, 0x00000001, 0x00000101, ++ 0x00000101, ++ 0x00000000, 0x00000000, 0x01000000, 0x01000000, 0x00000000, ++ 0x00000000, 0x01000000, 0x01000000, 0x00010000, 0x00010000, ++ 0x01010000, 0x01010000, 0x00010000, 0x00010000, 0x01010000, ++ 0x01010000, ++ }; ++ static const uint32_t perm[] = { ++ 0x00000000, 0x40000000, 0x00400000, 0x40400000, 0x00004000, ++ 0x40004000, 0x00404000, 0x40404000, 0x00000040, 0x40000040, ++ 0x00400040, 0x40400040, 0x00004040, 0x40004040, 0x00404040, ++ 0x40404040, ++ 0x00000000, 0x40000000, 0x00400000, 0x40400000, 0x00004000, ++ 0x40004000, 0x00404000, 0x40404000, 0x00000040, 0x40000040, ++ 0x00400040, 0x40400040, 0x00004040, 0x40004040, 0x00404040, ++ 0x40404040, ++ 0x00000000, 0x10000000, 0x00100000, 0x10100000, 0x00001000, ++ 0x10001000, 0x00101000, 0x10101000, 0x00000010, 0x10000010, ++ 0x00100010, 0x10100010, 0x00001010, 0x10001010, 0x00101010, ++ 0x10101010, ++ 0x00000000, 0x10000000, 0x00100000, 0x10100000, 0x00001000, ++ 0x10001000, 0x00101000, 0x10101000, 0x00000010, 0x10000010, ++ 0x00100010, 0x10100010, 0x00001010, 0x10001010, 0x00101010, ++ 0x10101010, ++ 0x00000000, 0x04000000, 0x00040000, 0x04040000, 0x00000400, ++ 0x04000400, 0x00040400, 0x04040400, 0x00000004, 0x04000004, ++ 0x00040004, 0x04040004, 0x00000404, 0x04000404, 0x00040404, ++ 0x04040404, ++ 0x00000000, 0x04000000, 0x00040000, 0x04040000, 0x00000400, ++ 0x04000400, 0x00040400, 0x04040400, 0x00000004, 0x04000004, ++ 0x00040004, 0x04040004, 0x00000404, 0x04000404, 0x00040404, ++ 0x04040404, ++ 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, ++ 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, ++ 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, ++ 0x01010101, ++ 0x00000000, 0x01000000, 0x00010000, 0x01010000, 0x00000100, ++ 0x01000100, 0x00010100, 0x01010100, 0x00000001, 0x01000001, ++ 0x00010001, 0x01010001, 0x00000101, 0x01000101, 0x00010101, ++ 0x01010101, ++ 0x00000000, 0x80000000, 0x00800000, 0x80800000, 0x00008000, ++ 0x80008000, 0x00808000, 0x80808000, 0x00000080, 0x80000080, ++ 0x00800080, 0x80800080, 0x00008080, 0x80008080, 0x00808080, ++ 0x80808080, ++ 0x00000000, 0x80000000, 0x00800000, 0x80800000, 0x00008000, ++ 0x80008000, 0x00808000, 0x80808000, 0x00000080, 0x80000080, ++ 0x00800080, 0x80800080, 0x00008080, 0x80008080, 0x00808080, ++ 0x80808080, ++ 0x00000000, 0x20000000, 0x00200000, 0x20200000, 0x00002000, ++ 0x20002000, 0x00202000, 0x20202000, 0x00000020, 0x20000020, ++ 0x00200020, 0x20200020, 0x00002020, 0x20002020, 0x00202020, ++ 0x20202020, ++ 0x00000000, 0x20000000, 0x00200000, 0x20200000, 0x00002000, ++ 0x20002000, 0x00202000, 0x20202000, 0x00000020, 0x20000020, ++ 0x00200020, 0x20200020, 0x00002020, 0x20002020, 0x00202020, ++ 0x20202020, ++ 0x00000000, 0x08000000, 0x00080000, 0x08080000, 0x00000800, ++ 0x08000800, 0x00080800, 0x08080800, 0x00000008, 0x08000008, ++ 0x00080008, 0x08080008, 0x00000808, 0x08000808, 0x00080808, ++ 0x08080808, ++ 0x00000000, 0x08000000, 0x00080000, 0x08080000, 0x00000800, ++ 0x08000800, 0x00080800, 0x08080800, 0x00000008, 0x08000008, ++ 0x00080008, 0x08080008, 0x00000808, 0x08000808, 0x00080808, ++ 0x08080808, ++ 0x00000000, 0x02000000, 0x00020000, 0x02020000, 0x00000200, ++ 0x02000200, 0x00020200, 0x02020200, 0x00000002, 0x02000002, ++ 0x00020002, 0x02020002, 0x00000202, 0x02000202, 0x00020202, ++ 0x02020202, ++ 0x00000000, 0x02000000, 0x00020000, 0x02020000, 0x00000200, ++ 0x02000200, 0x00020200, 0x02020200, 0x00000002, 0x02000002, ++ 0x00020002, 0x02020002, 0x00000202, 0x02000202, 0x00020202, ++ 0x02020202, ++ }; ++ static const uint32_t sxp[] = { ++ 0x00410100, 0x00010000, 0x40400000, 0x40410100, 0x00400000, ++ 0x40010100, 0x40010000, 0x40400000, 0x40010100, 0x00410100, ++ 0x00410000, 0x40000100, 0x40400100, 0x00400000, 0x00000000, ++ 0x40010000, 0x00010000, 0x40000000, 0x00400100, 0x00010100, ++ 0x40410100, 0x00410000, 0x40000100, 0x00400100, 0x40000000, ++ 0x00000100, 0x00010100, 0x40410000, 0x00000100, 0x40400100, ++ 0x40410000, 0x00000000, 0x00000000, 0x40410100, 0x00400100, ++ 0x40010000, 0x00410100, 0x00010000, 0x40000100, 0x00400100, ++ 0x40410000, 0x00000100, 0x00010100, 0x40400000, 0x40010100, ++ 0x40000000, 0x40400000, 0x00410000, 0x40410100, 0x00010100, ++ 0x00410000, 0x40400100, 0x00400000, 0x40000100, 0x40010000, ++ 0x00000000, 0x00010000, 0x00400000, 0x40400100, 0x00410100, ++ 0x40000000, 0x40410000, 0x00000100, 0x40010100, ++ 0x08021002, 0x00000000, 0x00021000, 0x08020000, 0x08000002, ++ 0x00001002, 0x08001000, 0x00021000, 0x00001000, 0x08020002, ++ 0x00000002, 0x08001000, 0x00020002, 0x08021000, 0x08020000, ++ 0x00000002, 0x00020000, 0x08001002, 0x08020002, 0x00001000, ++ 0x00021002, 0x08000000, 0x00000000, 0x00020002, 0x08001002, ++ 0x00021002, 0x08021000, 0x08000002, 0x08000000, 0x00020000, ++ 0x00001002, 0x08021002, 0x00020002, 0x08021000, 0x08001000, ++ 0x00021002, 0x08021002, 0x00020002, 0x08000002, 0x00000000, ++ 0x08000000, 0x00001002, 0x00020000, 0x08020002, 0x00001000, ++ 0x08000000, 0x00021002, 0x08001002, 0x08021000, 0x00001000, ++ 0x00000000, 0x08000002, 0x00000002, 0x08021002, 0x00021000, ++ 0x08020000, 0x08020002, 0x00020000, 0x00001002, 0x08001000, ++ 0x08001002, 0x00000002, 0x08020000, 0x00021000, ++ 0x20800000, 0x00808020, 0x00000020, 0x20800020, 0x20008000, ++ 0x00800000, 0x20800020, 0x00008020, 0x00800020, 0x00008000, ++ 0x00808000, 0x20000000, 0x20808020, 0x20000020, 0x20000000, ++ 0x20808000, 0x00000000, 0x20008000, 0x00808020, 0x00000020, ++ 0x20000020, 0x20808020, 0x00008000, 0x20800000, 0x20808000, ++ 0x00800020, 0x20008020, 0x00808000, 0x00008020, 0x00000000, ++ 0x00800000, 0x20008020, 0x00808020, 0x00000020, 0x20000000, ++ 0x00008000, 0x20000020, 0x20008000, 0x00808000, 0x20800020, ++ 0x00000000, 0x00808020, 0x00008020, 0x20808000, 0x20008000, ++ 0x00800000, 0x20808020, 0x20000000, 0x20008020, 0x20800000, ++ 0x00800000, 0x20808020, 0x00008000, 0x00800020, 0x20800020, ++ 0x00008020, 0x00800020, 0x00000000, 0x20808000, 0x20000020, ++ 0x20800000, 0x20008020, 0x00000020, 0x00808000, ++ 0x00080201, 0x02000200, 0x00000001, 0x02080201, 0x00000000, ++ 0x02080000, 0x02000201, 0x00080001, 0x02080200, 0x02000001, ++ 0x02000000, 0x00000201, 0x02000001, 0x00080201, 0x00080000, ++ 0x02000000, 0x02080001, 0x00080200, 0x00000200, 0x00000001, ++ 0x00080200, 0x02000201, 0x02080000, 0x00000200, 0x00000201, ++ 0x00000000, 0x00080001, 0x02080200, 0x02000200, 0x02080001, ++ 0x02080201, 0x00080000, 0x02080001, 0x00000201, 0x00080000, ++ 0x02000001, 0x00080200, 0x02000200, 0x00000001, 0x02080000, ++ 0x02000201, 0x00000000, 0x00000200, 0x00080001, 0x00000000, ++ 0x02080001, 0x02080200, 0x00000200, 0x02000000, 0x02080201, ++ 0x00080201, 0x00080000, 0x02080201, 0x00000001, 0x02000200, ++ 0x00080201, 0x00080001, 0x00080200, 0x02080000, 0x02000201, ++ 0x00000201, 0x02000000, 0x02000001, 0x02080200, ++ 0x01000000, 0x00002000, 0x00000080, 0x01002084, 0x01002004, ++ 0x01000080, 0x00002084, 0x01002000, 0x00002000, 0x00000004, ++ 0x01000004, 0x00002080, 0x01000084, 0x01002004, 0x01002080, ++ 0x00000000, 0x00002080, 0x01000000, 0x00002004, 0x00000084, ++ 0x01000080, 0x00002084, 0x00000000, 0x01000004, 0x00000004, ++ 0x01000084, 0x01002084, 0x00002004, 0x01002000, 0x00000080, ++ 0x00000084, 0x01002080, 0x01002080, 0x01000084, 0x00002004, ++ 0x01002000, 0x00002000, 0x00000004, 0x01000004, 0x01000080, ++ 0x01000000, 0x00002080, 0x01002084, 0x00000000, 0x00002084, ++ 0x01000000, 0x00000080, 0x00002004, 0x01000084, 0x00000080, ++ 0x00000000, 0x01002084, 0x01002004, 0x01002080, 0x00000084, ++ 0x00002000, 0x00002080, 0x01002004, 0x01000080, 0x00000084, ++ 0x00000004, 0x00002084, 0x01002000, 0x01000004, ++ 0x10000008, 0x00040008, 0x00000000, 0x10040400, 0x00040008, ++ 0x00000400, 0x10000408, 0x00040000, 0x00000408, 0x10040408, ++ 0x00040400, 0x10000000, 0x10000400, 0x10000008, 0x10040000, ++ 0x00040408, 0x00040000, 0x10000408, 0x10040008, 0x00000000, ++ 0x00000400, 0x00000008, 0x10040400, 0x10040008, 0x10040408, ++ 0x10040000, 0x10000000, 0x00000408, 0x00000008, 0x00040400, ++ 0x00040408, 0x10000400, 0x00000408, 0x10000000, 0x10000400, ++ 0x00040408, 0x10040400, 0x00040008, 0x00000000, 0x10000400, ++ 0x10000000, 0x00000400, 0x10040008, 0x00040000, 0x00040008, ++ 0x10040408, 0x00040400, 0x00000008, 0x10040408, 0x00040400, ++ 0x00040000, 0x10000408, 0x10000008, 0x10040000, 0x00040408, ++ 0x00000000, 0x00000400, 0x10000008, 0x10000408, 0x10040400, ++ 0x10040000, 0x00000408, 0x00000008, 0x10040008, ++ 0x00000800, 0x00000040, 0x00200040, 0x80200000, 0x80200840, ++ 0x80000800, 0x00000840, 0x00000000, 0x00200000, 0x80200040, ++ 0x80000040, 0x00200800, 0x80000000, 0x00200840, 0x00200800, ++ 0x80000040, 0x80200040, 0x00000800, 0x80000800, 0x80200840, ++ 0x00000000, 0x00200040, 0x80200000, 0x00000840, 0x80200800, ++ 0x80000840, 0x00200840, 0x80000000, 0x80000840, 0x80200800, ++ 0x00000040, 0x00200000, 0x80000840, 0x00200800, 0x80200800, ++ 0x80000040, 0x00000800, 0x00000040, 0x00200000, 0x80200800, ++ 0x80200040, 0x80000840, 0x00000840, 0x00000000, 0x00000040, ++ 0x80200000, 0x80000000, 0x00200040, 0x00000000, 0x80200040, ++ 0x00200040, 0x00000840, 0x80000040, 0x00000800, 0x80200840, ++ 0x00200000, 0x00200840, 0x80000000, 0x80000800, 0x80200840, ++ 0x80200000, 0x00200840, 0x00200800, 0x80000800, ++ 0x04100010, 0x04104000, 0x00004010, 0x00000000, 0x04004000, ++ 0x00100010, 0x04100000, 0x04104010, 0x00000010, 0x04000000, ++ 0x00104000, 0x00004010, 0x00104010, 0x04004010, 0x04000010, ++ 0x04100000, 0x00004000, 0x00104010, 0x00100010, 0x04004000, ++ 0x04104010, 0x04000010, 0x00000000, 0x00104000, 0x04000000, ++ 0x00100000, 0x04004010, 0x04100010, 0x00100000, 0x00004000, ++ 0x04104000, 0x00000010, 0x00100000, 0x00004000, 0x04000010, ++ 0x04104010, 0x00004010, 0x04000000, 0x00000000, 0x00104000, ++ 0x04100010, 0x04004010, 0x04004000, 0x00100010, 0x04104000, ++ 0x00000010, 0x00100010, 0x04004000, 0x04104010, 0x00100000, ++ 0x04100000, 0x04000010, 0x00104000, 0x00004010, 0x04004010, ++ 0x04100000, 0x00000010, 0x04104000, 0x00104010, 0x00000000, ++ 0x04000000, 0x04100010, 0x00004000, 0x00104010, ++ }; ++ ++ __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", "descrypt_Block"); ++ ++ // Allocate registers ++ Register src = A0; ++ Register dst = A1; ++ Register key = A2; ++ Register ip = A3; ++ Register tl = A4; ++ Register tr = A5; ++ Register of = A6; ++ Register hi = of; ++ Register lo = key; ++ Register t0 = T0; ++ Register t1 = T1; ++ Register t2 = T2; ++ Register t3 = T3; ++ Register t4 = T4; ++ Register t5 = T5; ++ Register t6 = T6; ++ Register t7 = T7; ++ Register t8 = T8; ++ Register t9 = A7; ++ Register ti = src; ++ ++ Label entry, loop; ++ ++ entry_enc = __ pc(); ++ __ li(of, -8); ++ __ b(entry); ++ ++ entry_dec = __ pc(); ++ __ li(of, 8); ++ __ addi_d(key, key, 120); ++ ++ __ bind(entry); ++ __ li(ip, (intptr_t)initPerm); ++ ++ // Initial permutation ++ __ ld_d(t0, src, 0); ++ for (int i = 0; i < 4; i++) { ++ __ bstrpick_d(t2, t0, 7 + 8 * (2 * i + 0), 4 + 8 * (2 * i + 0)); ++ __ bstrpick_d(t1, t0, 3 + 8 * (2 * i + 0), 0 + 8 * (2 * i + 0)); ++ __ bstrpick_d(t6, t0, 7 + 8 * (2 * i + 1), 4 + 8 * (2 * i + 1)); ++ __ bstrpick_d(t5, t0, 3 + 8 * (2 * i + 1), 0 + 8 * (2 * i + 1)); ++ __ alsl_d(t2, t2, ip, 2 - 1); ++ __ alsl_d(t1, t1, ip, 2 - 1); ++ __ alsl_d(t6, t6, ip, 2 - 1); ++ __ alsl_d(t5, t5, ip, 2 - 1); ++ __ ld_wu(t3, t2, 4 * 16 * (16 + (2 * i + 0) * 2 + 0)); ++ __ ld_wu(t2, t2, 4 * 16 * (00 + (2 * i + 0) * 2 + 0)); ++ __ ld_wu(t4, t1, 4 * 16 * (16 + (2 * i + 0) * 2 + 1)); ++ __ ld_wu(t1, t1, 4 * 16 * (00 + (2 * i + 0) * 2 + 1)); ++ __ ld_wu(t7, t6, 4 * 16 * (16 + (2 * i + 1) * 2 + 0)); ++ __ ld_wu(t6, t6, 4 * 16 * (00 + (2 * i + 1) * 2 + 0)); ++ __ ld_wu(t8, t5, 4 * 16 * (16 + (2 * i + 1) * 2 + 1)); ++ __ ld_wu(t5, t5, 4 * 16 * (00 + (2 * i + 1) * 2 + 1)); ++ if (i == 0) { ++ __ OR(tr, t4, t3); ++ __ OR(tl, t2, t1); ++ } else { ++ __ OR(tr, tr, t3); ++ __ OR(tl, tl, t2); ++ __ OR(tr, tr, t4); ++ __ OR(tl, tl, t1); ++ } ++ __ OR(tr, tr, t7); ++ __ OR(tl, tl, t6); ++ __ OR(tr, tr, t8); ++ __ OR(tl, tl, t5); ++ } ++ ++ __ li(ip, (intptr_t)sxp); ++ __ li(ti, 16); ++ __ bind(loop); ++ ++ __ ld_d(t0, key, 0); ++ __ rotri_w(t1, tr, 31); ++ ++ // s[0-3]p ++ __ bstrpick_w(t2, t1, 5, 0); ++ __ bstrpick_d(t3, t0, 7, 0); ++ __ bstrpick_w(t4, t1, 9, 4); ++ __ bstrpick_d(t5, t0, 15, 8); ++ __ bstrpick_w(t6, t1, 13, 8); ++ __ bstrpick_d(t7, t0, 23, 16); ++ __ bstrpick_w(t8, t1, 17, 12); ++ __ bstrpick_d(t9, t0, 31, 24); ++ __ XOR(t3, t2, t3); ++ __ XOR(t5, t4, t5); ++ __ XOR(t7, t6, t7); ++ __ XOR(t9, t8, t9); ++ __ alsl_d(t3, t3, ip, 2 - 1); ++ __ alsl_d(t5, t5, ip, 2 - 1); ++ __ alsl_d(t7, t7, ip, 2 - 1); ++ __ alsl_d(t9, t9, ip, 2 - 1); ++ __ ld_wu(t3, t3, 4 * 64 * 0); ++ __ ld_wu(t5, t5, 4 * 64 * 1); ++ __ ld_wu(t7, t7, 4 * 64 * 2); ++ __ ld_wu(t9, t9, 4 * 64 * 3); ++ __ XOR(tl, tl, t3); ++ __ XOR(tl, tl, t5); ++ __ XOR(tl, tl, t7); ++ __ XOR(tl, tl, t9); ++ ++ // s[4-7]p ++ __ bstrpick_w(t2, t1, 21, 16); ++ __ bstrpick_d(t3, t0, 39, 32); ++ __ bstrpick_w(t4, t1, 25, 20); ++ __ bstrpick_d(t5, t0, 47, 40); ++ __ bstrpick_w(t6, t1, 29, 24); ++ __ bstrpick_d(t7, t0, 55, 48); ++ __ bstrpick_w(t8, tr, 31, 27); ++ __ bstrpick_d(t9, t0, 63, 56); ++ __ bstrins_w(t8, tr, 5, 5); ++ __ XOR(t3, t2, t3); ++ __ XOR(t5, t4, t5); ++ __ XOR(t7, t6, t7); ++ __ XOR(t9, t8, t9); ++ __ alsl_d(t3, t3, ip, 2 - 1); ++ __ alsl_d(t5, t5, ip, 2 - 1); ++ __ alsl_d(t7, t7, ip, 2 - 1); ++ __ alsl_d(t9, t9, ip, 2 - 1); ++ __ ld_wu(t3, t3, 4 * 64 * 4); ++ __ ld_wu(t5, t5, 4 * 64 * 5); ++ __ ld_wu(t7, t7, 4 * 64 * 6); ++ __ ld_wu(t9, t9, 4 * 64 * 7); ++ __ XOR(tl, tl, t3); ++ __ XOR(tl, tl, t5); ++ __ XOR(tl, tl, t7); ++ __ XOR(tl, tl, t9); ++ ++ __ move(t0, tl); ++ __ move(tl, tr); ++ __ move(tr, t0); ++ __ sub_d(key, key, of); ++ ++ __ addi_w(ti, ti, -1); ++ __ bnez(ti, loop); ++ ++ __ move(t0, tl); ++ __ move(tl, tr); ++ __ move(tr, t0); ++ ++ // Perm ++ __ li(ip, (intptr_t)perm); ++ for (int i = 0; i < 2; i++) { ++ __ bstrpick_w(t0, tl, 3 + 4 * (4 * i + 0), 4 * (4 * i + 0)); ++ __ bstrpick_w(t1, tr, 3 + 4 * (4 * i + 0), 4 * (4 * i + 0)); ++ __ bstrpick_w(t2, tl, 3 + 4 * (4 * i + 1), 4 * (4 * i + 1)); ++ __ bstrpick_w(t3, tr, 3 + 4 * (4 * i + 1), 4 * (4 * i + 1)); ++ __ bstrpick_w(t4, tl, 3 + 4 * (4 * i + 2), 4 * (4 * i + 2)); ++ __ bstrpick_w(t5, tr, 3 + 4 * (4 * i + 2), 4 * (4 * i + 2)); ++ __ bstrpick_w(t6, tl, 3 + 4 * (4 * i + 3), 4 * (4 * i + 3)); ++ __ bstrpick_w(t7, tr, 3 + 4 * (4 * i + 3), 4 * (4 * i + 3)); ++ __ alsl_d(t0, t0, ip, 2 - 1); ++ __ alsl_d(t1, t1, ip, 2 - 1); ++ __ alsl_d(t2, t2, ip, 2 - 1); ++ __ alsl_d(t3, t3, ip, 2 - 1); ++ __ alsl_d(t4, t4, ip, 2 - 1); ++ __ alsl_d(t5, t5, ip, 2 - 1); ++ __ alsl_d(t6, t6, ip, 2 - 1); ++ __ alsl_d(t7, t7, ip, 2 - 1); ++ __ ld_wu(t0, t0, 4 * 16 * (0 + (4 * i + 0))); ++ __ ld_wu(t1, t1, 4 * 16 * (8 + (4 * i + 0))); ++ __ ld_wu(t2, t2, 4 * 16 * (0 + (4 * i + 1))); ++ __ ld_wu(t3, t3, 4 * 16 * (8 + (4 * i + 1))); ++ __ ld_wu(t4, t4, 4 * 16 * (0 + (4 * i + 2))); ++ __ ld_wu(t5, t5, 4 * 16 * (8 + (4 * i + 2))); ++ __ ld_wu(t6, t6, 4 * 16 * (0 + (4 * i + 3))); ++ __ ld_wu(t7, t7, 4 * 16 * (8 + (4 * i + 3))); ++ if (i == 0) { ++ __ OR(hi, t0, t1); ++ __ OR(lo, t2, t3); ++ } else { ++ __ OR(hi, hi, t0); ++ __ OR(lo, lo, t2); ++ __ OR(hi, hi, t1); ++ __ OR(lo, lo, t3); ++ } ++ __ OR(hi, hi, t4); ++ __ OR(lo, lo, t6); ++ __ OR(hi, hi, t5); ++ __ OR(lo, lo, t7); ++ } ++ ++ __ st_w(lo, dst, 0); ++ __ st_w(hi, dst, 4); ++ ++ __ jr(RA); ++ } ++ ++ // Arguments: ++ // ++ // Inputs: + // A0 - byte[] source+offset + // A1 - int[] SHA.state + // A2 - int offset @@ -62578,8 +63563,8 @@ index 00000000000..f9b95b56af8 + SharedRuntime::throw_delayed_StackOverflowError)); + + // Initialize table for copy memory (arraycopy) check. -+ if (UnsafeCopyMemory::_table == nullptr) { -+ UnsafeCopyMemory::create_table(8 ZGC_ONLY(+ (UseZGC && ZGenerational ? 14 : 0))); ++ if (UnsafeMemoryAccess::_table == nullptr) { ++ UnsafeMemoryAccess::create_table(8 + 4 ZGC_ONLY(+ (UseZGC && ZGenerational ? 14 : 0))); // 8 for copyMemory; 4 for setMemory + } + + if (UseCRC32Intrinsics) { @@ -62696,6 +63681,10 @@ index 00000000000..f9b95b56af8 + StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_aescrypt_decryptBlock(true); + } + ++ if (UseDESIntrinsics) { ++ generate_descrypt_Block(StubRoutines::_descrypt_encryptBlock, StubRoutines::_descrypt_decryptBlock); ++ } ++ + if (UseMD5Intrinsics) { + generate_md5_implCompress("md5_implCompress", StubRoutines::_md5_implCompress, StubRoutines::_md5_implCompressMB); + } @@ -63064,13 +64053,13 @@ index 00000000000..3cef08cb261 +}; diff --git a/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp new file mode 100644 -index 00000000000..1d487c4e978 +index 00000000000..0311a343810 --- /dev/null +++ b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp @@ -0,0 +1,2118 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -63169,7 +64158,7 @@ index 00000000000..1d487c4e978 + FloatRegister floatreg = as_FloatRegister(i + FA0->encoding()); + Label isdouble, done; + -+ __ andi(AT, A3, 1 << i); ++ __ test_bit(AT, A3, i); + __ bnez(AT, isdouble); + __ fld_s(floatreg, SP, (10 + i) * wordSize); + __ b(done); @@ -63921,7 +64910,7 @@ index 00000000000..1d487c4e978 +#ifdef ASSERT + { Label L; + __ ld_w(T0, Rmethod, in_bytes(Method::access_flags_offset())); -+ __ andi(T0, T0, JVM_ACC_SYNCHRONIZED); ++ __ test_bit(T0, T0, exact_log2(JVM_ACC_SYNCHRONIZED)); + __ bne(T0, R0, L); + __ stop("method doesn't need synchronization"); + __ bind(L); @@ -63931,7 +64920,7 @@ index 00000000000..1d487c4e978 + { + Label done; + __ ld_w(T0, Rmethod, in_bytes(Method::access_flags_offset())); -+ __ andi(T2, T0, JVM_ACC_STATIC); ++ __ test_bit(T2, T0, exact_log2(JVM_ACC_STATIC)); + __ ld_d(T0, LVP, Interpreter::local_offset_in_bytes(0)); + __ beq(T2, R0, done); + __ load_mirror(T0, Rmethod, SCR2, SCR1); @@ -64144,14 +65133,14 @@ index 00000000000..1d487c4e978 + __ ld_w(T0, Rmethod, in_bytes(Method::access_flags_offset())); + { + Label L; -+ __ andi(AT, T0, JVM_ACC_NATIVE); ++ __ test_bit(AT, T0, exact_log2(JVM_ACC_NATIVE)); + __ bne(AT, R0, L); + __ stop("tried to execute native method as non-native"); + __ bind(L); + } + { + Label L; -+ __ andi(AT, T0, JVM_ACC_ABSTRACT); ++ __ test_bit(AT, T0, exact_log2(JVM_ACC_ABSTRACT)); + __ beq(AT, R0, L); + __ stop("tried to execute abstract method in interpreter"); + __ bind(L); @@ -64192,7 +65181,7 @@ index 00000000000..1d487c4e978 + { + Label L; + __ ld_w(T0, Rmethod, in_bytes(Method::access_flags_offset())); -+ __ andi(AT, T0, JVM_ACC_SYNCHRONIZED); ++ __ test_bit(AT, T0, exact_log2(JVM_ACC_SYNCHRONIZED)); + __ beq(AT, R0, L); + __ stop("method needs synchronization"); + __ bind(L); @@ -64247,7 +65236,7 @@ index 00000000000..1d487c4e978 + // LoongArch ABI: caller does not reserve space for the register auguments. + // A0 and A1(if needed) + __ ld_w(AT, Rmethod, in_bytes(Method::access_flags_offset())); -+ __ andi(AT, AT, JVM_ACC_STATIC); ++ __ test_bit(AT, AT, exact_log2(JVM_ACC_STATIC)); + __ beq(AT, R0, Lstatic); + __ addi_d(t, t, 1); + __ bind(Lstatic); @@ -64327,7 +65316,7 @@ index 00000000000..1d487c4e978 + { + Label L; + __ ld_w(t, method, in_bytes(Method::access_flags_offset())); -+ __ andi(AT, t, JVM_ACC_STATIC); ++ __ test_bit(AT, t, exact_log2(JVM_ACC_STATIC)); + __ beq(AT, R0, L); + + // get mirror @@ -64559,7 +65548,7 @@ index 00000000000..1d487c4e978 + const Register monitor_reg = T0; + Label L; + __ ld_w(t, method, in_bytes(Method::access_flags_offset())); -+ __ andi(t, t, JVM_ACC_SYNCHRONIZED); ++ __ test_bit(t, t, exact_log2(JVM_ACC_SYNCHRONIZED)); + __ addi_d(monitor_reg, FP, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock)); + __ beq(t, R0, L); + // the code below should be shared with interpreter macro assembler implementation @@ -64733,14 +65722,14 @@ index 00000000000..1d487c4e978 + __ ld_d(AT, Rmethod, in_bytes(Method::access_flags_offset())); + { + Label L; -+ __ andi(T2, AT, JVM_ACC_NATIVE); ++ __ test_bit(T2, AT, exact_log2(JVM_ACC_NATIVE)); + __ beq(T2, R0, L); + __ stop("tried to execute native method as non-native"); + __ bind(L); + } + { + Label L; -+ __ andi(T2, AT, JVM_ACC_ABSTRACT); ++ __ test_bit(T2, AT, exact_log2(JVM_ACC_ABSTRACT)); + __ beq(T2, R0, L); + __ stop("tried to execute abstract method in interpreter"); + __ bind(L); @@ -64787,8 +65776,8 @@ index 00000000000..1d487c4e978 +#ifdef ASSERT + { Label L; + __ ld_w(AT, Rmethod, in_bytes(Method::access_flags_offset())); -+ __ andi(T2, AT, JVM_ACC_SYNCHRONIZED); -+ __ beq(T2, R0, L); ++ __ test_bit(AT, AT, exact_log2(JVM_ACC_SYNCHRONIZED)); ++ __ beqz(AT, L); + __ stop("method needs synchronization"); + __ bind(L); + } @@ -65232,13 +66221,13 @@ index 00000000000..9278dcfafc3 +#endif // CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP diff --git a/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp b/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp new file mode 100644 -index 00000000000..74115edea62 +index 00000000000..d89e1079568 --- /dev/null +++ b/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp -@@ -0,0 +1,4077 @@ +@@ -0,0 +1,4055 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -66295,12 +67284,8 @@ index 00000000000..74115edea62 + // since both types share the bastore bytecode. + __ load_klass(T4, A1); + __ ld_w(T4, T4, in_bytes(Klass::layout_helper_offset())); -+ -+ int diffbit = Klass::layout_helper_boolean_diffbit(); -+ __ li(AT, diffbit); -+ + Label L_skip; -+ __ andr(AT, T4, AT); ++ __ test_bit(AT, T4, exact_log2(Klass::layout_helper_boolean_diffbit())); + __ beq(AT, R0, L_skip); + __ andi(FSR, FSR, 0x1); + __ bind(L_skip); @@ -66923,7 +67908,7 @@ index 00000000000..74115edea62 + __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, + T1, false, Assembler::zero, + UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); -+ __ beq(R0, R0, dispatch); ++ __ b(dispatch); + } + __ bind(no_mdo); + // Increment backedge counter in MethodCounters* @@ -67365,9 +68350,8 @@ index 00000000000..74115edea62 + __ ld_d(c_rarg1, aaddress(0)); + __ load_klass(LVP, c_rarg1); + __ ld_w(LVP, Address(LVP, Klass::access_flags_offset())); -+ __ li(AT, JVM_ACC_HAS_FINALIZER); -+ __ andr(AT, AT, LVP); + Label skip_register_finalizer; ++ __ test_bit(AT, LVP, exact_log2(JVM_ACC_HAS_FINALIZER)); + __ beqz(AT, skip_register_finalizer); + + __ call_VM(noreg, CAST_FROM_FN_PTR(address, @@ -67386,7 +68370,7 @@ index 00000000000..74115edea62 + if (_desc->bytecode() != Bytecodes::_return_register_finalizer) { + Label no_safepoint; + __ ld_d(AT, Address(TREG, JavaThread::polling_word_offset())); -+ __ andi(AT, AT, 1 << exact_log2(SafepointMechanism::poll_bit())); ++ __ test_bit(AT, AT, exact_log2(SafepointMechanism::poll_bit())); + __ beqz(AT, no_safepoint); + __ push(state); + __ push_cont_fastpath(TREG); @@ -67518,7 +68502,9 @@ index 00000000000..74115edea62 + __ ld_bu(flags, Address(cache, in_bytes(ResolvedFieldEntry::flags_offset()))); + + // TOS state -+ __ ld_bu(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset()))); ++ if (tos_state != noreg) { ++ __ ld_bu(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset()))); ++ } + + // Klass overwrite register + if (is_static) { @@ -67557,7 +68543,7 @@ index 00000000000..74115edea62 + + // maybe push appendix to arguments (just before return address) + Label L_no_push; -+ __ andi(AT, flags, 1 << ResolvedMethodEntry::has_appendix_shift); ++ __ test_bit(AT, flags, ResolvedMethodEntry::has_appendix_shift); + __ beqz(AT, L_no_push); + // invokehandle uses an index into the resolved references array + __ ld_hu(ref_index, Address(cache, in_bytes(ResolvedMethodEntry::resolved_references_index_offset()))); @@ -67591,9 +68577,9 @@ index 00000000000..74115edea62 + // Otherwise, the registers will be populated with the klass and method. + + Label NotVirtual; Label NotVFinal; Label Done; -+ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_forced_virtual_shift); ++ __ test_bit(AT, flags, ResolvedMethodEntry::is_forced_virtual_shift); + __ beqz(AT, NotVirtual); -+ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ test_bit(AT, flags, ResolvedMethodEntry::is_vfinal_shift); + __ beqz(AT, NotVFinal); + __ ld_d(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); + __ b(Done); @@ -67621,7 +68607,7 @@ index 00000000000..74115edea62 + + // method_or_table_index can either be an itable index or a method depending on the virtual final flag + Label NotVFinal; Label Done; -+ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ test_bit(AT, flags, ResolvedMethodEntry::is_vfinal_shift); + __ beqz(AT, NotVFinal); + __ ld_d(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); + __ b(Done); @@ -67672,7 +68658,7 @@ index 00000000000..74115edea62 + Label L_no_push; + // Check if there is an appendix + __ ld_bu(index, Address(cache, in_bytes(ResolvedIndyEntry::flags_offset()))); -+ __ andi(AT, index, 1UL << ResolvedIndyEntry::has_appendix_shift); ++ __ test_bit(AT, index, ResolvedIndyEntry::has_appendix_shift); + __ beqz(AT, L_no_push); + + // Get appendix @@ -67777,10 +68763,8 @@ index 00000000000..74115edea62 + load_resolved_field_entry(obj, cache, tos_state, off, flags, is_static); + + { -+ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); -+ __ andr(scratch, scratch, flags); -+ + Label notVolatile; ++ __ test_bit(scratch, flags, ResolvedFieldEntry::is_volatile_shift); + __ beq(scratch, R0, notVolatile); + __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); @@ -68025,16 +69009,13 @@ index 00000000000..74115edea62 + + Label Done; + { -+ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); -+ __ andr(scratch, scratch, flags); -+ + Label notVolatile; ++ __ test_bit(scratch, flags, ResolvedFieldEntry::is_volatile_shift); + __ beq(scratch, R0, notVolatile); + __ membar(Assembler::Membar_mask_bits(__ StoreStore | __ LoadStore)); + __ bind(notVolatile); + } + -+ + Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble; + + assert(btos == 0, "change code, btos != 0"); @@ -68292,20 +69273,13 @@ index 00000000000..74115edea62 + + // access constant pool cache + __ load_field_entry(T3, T2); -+ -+ // Must prevent reordering of the following cp cache loads with bytecode load -+ __ membar(__ LoadLoad); -+ __ push(T0); -+ // T2: field offset, T0: TOS, T1: flags -+ load_resolved_field_entry(T3, T3, T0, T2, T1); -+ __ pop(T0); ++ // T2: field offset, T3: field holder, T1: flags ++ load_resolved_field_entry(T3, T3, noreg, T2, T1); + + Label Done; + { -+ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); -+ __ andr(scratch, scratch, T1); -+ + Label notVolatile; ++ __ test_bit(scratch, T1, ResolvedFieldEntry::is_volatile_shift); + __ beq(scratch, R0, notVolatile); + __ membar(Assembler::Membar_mask_bits(__ StoreStore | __ LoadStore)); + __ bind(notVolatile); @@ -68393,18 +69367,13 @@ index 00000000000..74115edea62 + // access constant pool cache + __ load_field_entry(T3, T2); + -+ // Must prevent reordering of the following cp cache loads with bytecode load -+ __ membar(__ LoadLoad); -+ + // replace index with field offset from cache entry + __ load_sized_value(T2, Address(T3, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ ld_bu(T1, Address(T3, in_bytes(ResolvedFieldEntry::flags_offset()))); + + { -+ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); -+ __ andr(scratch, scratch, T1); -+ + Label notVolatile; ++ __ test_bit(scratch, T1, ResolvedFieldEntry::is_volatile_shift); + __ beqz(scratch, notVolatile); + __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); @@ -68474,8 +69443,7 @@ index 00000000000..74115edea62 + + { + __ ld_bu(AT, Address(T3, in_bytes(ResolvedFieldEntry::flags_offset()))); -+ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); -+ __ andr(scratch, scratch, AT); ++ __ test_bit(scratch, AT, ResolvedFieldEntry::is_volatile_shift); + + Label notVolatile; + __ beq(scratch, R0, notVolatile); @@ -68554,7 +69522,7 @@ index 00000000000..74115edea62 + + // Test for an invoke of a final method + Label notFinal; -+ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ test_bit(AT, flags, ResolvedMethodEntry::is_vfinal_shift); + __ beq(AT, R0, notFinal); + + Register method = index; // method must be Rmethod @@ -68683,7 +69651,7 @@ index 00000000000..74115edea62 + // Special case of invokeinterface called for virtual method of + // java.lang.Object. See cpCache.cpp for details. + Label notObjectMethod; -+ __ andi(AT, T1, 1 << ResolvedMethodEntry::is_forced_virtual_shift); ++ __ test_bit(AT, T1, ResolvedMethodEntry::is_forced_virtual_shift); + __ beqz(AT, notObjectMethod); + + invokevirtual_helper(Rmethod, T3, T1); @@ -68695,7 +69663,7 @@ index 00000000000..74115edea62 + + // Check for private method invocation - indicated by vfinal + Label notVFinal; -+ __ andi(AT, T1, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ test_bit(AT, T1, ResolvedMethodEntry::is_vfinal_shift); + __ beqz(AT, notVFinal); + + // Get receiver klass into FSR @@ -68891,15 +69859,14 @@ index 00000000000..74115edea62 + // get InstanceKlass + __ load_resolved_klass_at_index(A1, A2, T3); + -+ // make sure klass is initialized & doesn't have finalizer -+ // make sure klass is fully initialized -+ __ ld_hu(T1, T3, in_bytes(InstanceKlass::init_state_offset())); -+ __ addi_d(AT, T1, - (int)InstanceKlass::fully_initialized); -+ __ bnez(AT, slow_case); ++ // make sure klass is initialized ++ assert(VM_Version::supports_fast_class_init_checks(), "Optimization requires support for fast class initialization checks"); ++ __ clinit_barrier(T3, T1, nullptr /*L_fast_path*/, &slow_case); + -+ // has_finalizer ++ // get instance_size in InstanceKlass (scaled to a count of bytes) + __ ld_w(T0, T3, in_bytes(Klass::layout_helper_offset()) ); -+ __ andi(AT, T0, Klass::_lh_instance_slow_path_bit); ++ // test to see if is malformed in some way ++ __ test_bit(AT, T0, exact_log2(Klass::_lh_instance_slow_path_bit)); + __ bnez(AT, slow_case); + + // Allocate the instance: @@ -69101,7 +70068,7 @@ index 00000000000..74115edea62 + + // Collect counts on whether this test sees nulls a lot or not. + if (ProfileInterpreter) { -+ __ beq(R0, R0, done); ++ __ b(done); + __ bind(is_null); + __ profile_null_seen(T3); + } else { @@ -69315,13 +70282,13 @@ index 00000000000..74115edea62 +} diff --git a/src/hotspot/cpu/loongarch/upcallLinker_loongarch_64.cpp b/src/hotspot/cpu/loongarch/upcallLinker_loongarch_64.cpp new file mode 100644 -index 00000000000..19491e55251 +index 00000000000..e05ab577f0c --- /dev/null +++ b/src/hotspot/cpu/loongarch/upcallLinker_loongarch_64.cpp -@@ -0,0 +1,341 @@ +@@ -0,0 +1,345 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. -+ * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2021, 2024, Loongson Technology. 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 @@ -69565,9 +70532,13 @@ index 00000000000..19491e55251 + __ mov_metadata(Rmethod, entry); + __ st_d(Rmethod, TREG, in_bytes(JavaThread::callee_target_offset())); // just in case callee is deoptimized + ++ __ push_cont_fastpath(TREG); ++ + __ ld_d(T4, Rmethod, in_bytes(Method::from_compiled_offset())); + __ jalr(T4); + ++ __ pop_cont_fastpath(TREG); ++ + // return value shuffle + if (!needs_return_buffer) { +#ifdef ASSERT @@ -69729,13 +70700,13 @@ index 00000000000..5b9f7b78981 +#endif // CPU_LOONGARCH_VMSTRUCTS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp b/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp new file mode 100644 -index 00000000000..c30bf3bf416 +index 00000000000..8a4e1fd2aa5 --- /dev/null +++ b/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp -@@ -0,0 +1,514 @@ +@@ -0,0 +1,521 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -70102,6 +71073,10 @@ index 00000000000..c30bf3bf416 + FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); + } + ++ if (FLAG_IS_DEFAULT(UseDESIntrinsics)) { ++ FLAG_SET_DEFAULT(UseDESIntrinsics, true); ++ } ++ + if (FLAG_IS_DEFAULT(UseCRC32)) { + FLAG_SET_DEFAULT(UseCRC32, true); + } @@ -70149,6 +71124,9 @@ index 00000000000..c30bf3bf416 + FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); + } + ++ if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { ++ FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); ++ } +#endif + + // This machine allows unaligned memory accesses @@ -70249,13 +71227,13 @@ index 00000000000..c30bf3bf416 +} diff --git a/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp b/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp new file mode 100644 -index 00000000000..04bd6942dc2 +index 00000000000..e8f0cd799d0 --- /dev/null +++ b/src/hotspot/cpu/loongarch/vm_version_loongarch.hpp -@@ -0,0 +1,308 @@ +@@ -0,0 +1,311 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -70550,10 +71528,13 @@ index 00000000000..04bd6942dc2 + static bool supports_lam_bh() { return _features & CPU_LAM_BH; } + static bool supports_lamcas() { return _features & CPU_LAMCAS; } + ++ // LoongArch64 supports fast class initialization checks + static bool supports_fast_class_init_checks() { return true; } + static bool supports_float16() { return UseLSX; } + constexpr static bool supports_stack_watermark_barrier() { return true; } + ++ constexpr static bool supports_recursive_lightweight_locking() { return true; } ++ + // Check intrinsic support + static bool is_intrinsic_supported(vmIntrinsicID id); + @@ -70824,13 +71805,13 @@ index 00000000000..03b53dc81f8 +#endif // CPU_LOONGARCH_VMSTORAGE_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp b/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp new file mode 100644 -index 00000000000..ab12021832d +index 00000000000..772e5c02c9c --- /dev/null +++ b/src/hotspot/cpu/loongarch/vtableStubs_loongarch_64.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -70855,10 +71836,10 @@ index 00000000000..ab12021832d + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" ++#include "code/compiledIC.hpp" +#include "code/vtableStubs.hpp" +#include "interp_masm_loongarch.hpp" +#include "memory/resourceArea.hpp" -+#include "oops/compiledICHolder.hpp" +#include "oops/klass.inline.hpp" +#include "oops/klassVtable.hpp" +#include "runtime/sharedRuntime.hpp" @@ -71023,14 +72004,14 @@ index 00000000000..ab12021832d + } +#endif // PRODUCT + -+ const Register holder_klass_reg = T1; // declaring interface klass (DECC) ++ const Register holder_klass_reg = T1; // declaring interface klass (DEFC) + const Register resolved_klass_reg = Rmethod; // resolved interface klass (REFC) -+ const Register icholder_reg = T1; ++ const Register icdata_reg = T1; + + Label L_no_such_interface; + -+ __ ld_d(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset())); -+ __ ld_d(holder_klass_reg, Address(icholder_reg, CompiledICHolder::holder_metadata_offset())); ++ __ ld_d(resolved_klass_reg, Address(icdata_reg, CompiledICData::itable_refc_klass_offset())); ++ __ ld_d(holder_klass_reg, Address(icdata_reg, CompiledICData::itable_defc_klass_offset())); + + // get receiver klass (also an implicit null-check) + address npe_addr = __ pc(); @@ -71140,8 +72121,37 @@ index 00000000000..ab12021832d + const unsigned int icache_line_size = wordSize; + return icache_line_size; +} +diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp +index 1fcf4b10862..28929e63466 100644 +--- a/src/hotspot/cpu/zero/vm_version_zero.cpp ++++ b/src/hotspot/cpu/zero/vm_version_zero.cpp +@@ -23,6 +23,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "asm/assembler.inline.hpp" + #include "memory/resourceArea.hpp" +@@ -66,6 +72,11 @@ void VM_Version::initialize() { + FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); + } + ++ if (UseDESIntrinsics) { ++ warning("DES intrinsics are not available on this CPU"); ++ FLAG_SET_DEFAULT(UseDESIntrinsics, false); ++ } ++ + if (UseFMA) { + warning("FMA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseFMA, false); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp -index 3fc025e5100..3e421c369d7 100644 +index 20d3c99cd3e..b441601c5ab 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -23,6 +23,12 @@ @@ -71156,8 +72166,8 @@ index 3fc025e5100..3e421c369d7 100644 + // no precompiled headers #include "classfile/vmSymbols.hpp" - #include "code/icBuffer.hpp" -@@ -2249,6 +2255,12 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { + #include "code/vtableStubs.hpp" +@@ -2325,6 +2331,12 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { return false; } @@ -71170,7 +72180,7 @@ index 3fc025e5100..3e421c369d7 100644 #ifdef __GLIBC__ // For Glibc, print a one-liner with the malloc tunables. // Most important and popular is MALLOC_ARENA_MAX, but we are -@@ -2465,7 +2477,7 @@ void os::print_memory_info(outputStream* st) { +@@ -2543,7 +2555,7 @@ void os::print_memory_info(outputStream* st) { // before "flags" so if we find a second "model name", then the // "flags" field is considered missing. static bool print_model_name_and_flags(outputStream* st, char* buf, size_t buflen) { @@ -71179,7 +72189,7 @@ index 3fc025e5100..3e421c369d7 100644 // Other platforms have less repetitive cpuinfo files FILE *fp = os::fopen("/proc/cpuinfo", "r"); if (fp) { -@@ -2577,7 +2589,7 @@ void os::jfr_report_memory_info() { +@@ -2655,7 +2667,7 @@ void os::jfr_report_memory_info() { #endif // INCLUDE_JFR @@ -71188,7 +72198,7 @@ index 3fc025e5100..3e421c369d7 100644 const char* search_string = "model name"; #elif defined(M68K) const char* search_string = "CPU"; -@@ -4401,6 +4413,44 @@ void os::Linux::numa_init() { +@@ -4558,6 +4570,44 @@ void os::Linux::numa_init() { // If there's only one node (they start from 0) or if the process // is bound explicitly to a single node using membind, disable NUMA UseNUMA = false; @@ -71234,7 +72244,7 @@ index 3fc025e5100..3e421c369d7 100644 LogTarget(Info,os) log; LogStream ls(log); diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp -index 4b2ccf8e370..5eaa98414ca 100644 +index 6b902e82802..0f43a32ea44 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -22,6 +22,12 @@ @@ -71250,7 +72260,7 @@ index 4b2ccf8e370..5eaa98414ca 100644 #ifndef OS_LINUX_OS_LINUX_HPP #define OS_LINUX_OS_LINUX_HPP -@@ -190,6 +196,8 @@ class os::Linux { +@@ -192,6 +198,8 @@ class os::Linux { // none present @@ -71260,7 +72270,7 @@ index 4b2ccf8e370..5eaa98414ca 100644 static void numa_init(); diff --git a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp -index 446449a40e0..0f70070713f 100644 +index a6b26928520..7eab09e2e84 100644 --- a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp +++ b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp @@ -22,6 +22,12 @@ @@ -71275,9 +72285,9 @@ index 446449a40e0..0f70070713f 100644 + #include "precompiled.hpp" #include "logging/log.hpp" - #include "runtime/os.hpp" -@@ -43,6 +49,8 @@ - #define SYS_membarrier 283 + #include "os_linux.hpp" +@@ -45,6 +51,8 @@ + #define SYS_membarrier 389 #elif defined(ALPHA) #define SYS_membarrier 517 + #elif defined(LOONGARCH) @@ -71285,179 +72295,6 @@ index 446449a40e0..0f70070713f 100644 #else #error define SYS_membarrier for the arch #endif -diff --git a/src/hotspot/os_cpu/linux_loongarch/amcas_asm.h b/src/hotspot/os_cpu/linux_loongarch/amcas_asm.h -new file mode 100644 -index 00000000000..305974a178f ---- /dev/null -+++ b/src/hotspot/os_cpu/linux_loongarch/amcas_asm.h -@@ -0,0 +1,167 @@ -+/* -+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2023, Loongson Technology. 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 __AMCAS_ASM_H__ -+#define __AMCAS_ASM_H__ -+ asm( -+ ".macro parse_r var r \n\t" -+ "\\var = -1 \n\t" -+ ".ifc \\r, $r0 \n\t" -+ "\\var = 0 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r1 \n\t" -+ "\\var = 1 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r2 \n\t" -+ "\\var = 2 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r3 \n\t" -+ "\\var = 3 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r4 \n\t" -+ "\\var = 4 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r5 \n\t" -+ "\\var = 5 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r6 \n\t" -+ "\\var = 6 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r7 \n\t" -+ "\\var = 7 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r8 \n\t" -+ "\\var = 8 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r9 \n\t" -+ "\\var = 9 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r10 \n\t" -+ "\\var = 10 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r11 \n\t" -+ "\\var = 11 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r12 \n\t" -+ "\\var = 12 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r13 \n\t" -+ "\\var = 13 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r14 \n\t" -+ "\\var = 14 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r15 \n\t" -+ "\\var = 15 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r16 \n\t" -+ "\\var = 16 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r17 \n\t" -+ "\\var = 17 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r18 \n\t" -+ "\\var = 18 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r19 \n\t" -+ "\\var = 19 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r20 \n\t" -+ "\\var = 20 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r21 \n\t" -+ "\\var = 21 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r22 \n\t" -+ "\\var = 22 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r23 \n\t" -+ "\\var = 23 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r24 \n\t" -+ "\\var = 24 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r25 \n\t" -+ "\\var = 25 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r26 \n\t" -+ "\\var = 26 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r27 \n\t" -+ "\\var = 27 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r28 \n\t" -+ "\\var = 28 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r29 \n\t" -+ "\\var = 29 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r30 \n\t" -+ "\\var = 30 \n\t" -+ ".endif \n\t" -+ ".ifc \\r, $r31 \n\t" -+ "\\var = 31 \n\t" -+ ".endif \n\t" -+ ".iflt \\var \n\t" -+ ".error \n\t" -+ ".endif \n\t" -+ ".endm \n\t" -+ -+ ".macro amcas_w rd, rk, rj \n\t" -+ "parse_r d, \\rd \n\t" -+ "parse_r j, \\rj \n\t" -+ "parse_r k, \\rk \n\t" -+ ".word ((0b00111000010110010 << 15) | (k << 10) | (j << 5) | d) \n\t" -+ ".endm \n\t" -+ -+ ".macro amcas_d rd, rk, rj \n\t" -+ "parse_r d, \\rd \n\t" -+ "parse_r j, \\rj \n\t" -+ "parse_r k, \\rk \n\t" -+ ".word ((0b00111000010110011 << 15) | (k << 10) | (j << 5) | d) \n\t" -+ ".endm \n\t" -+ -+ ".macro amcas_db_b rd, rk, rj \n\t" -+ "parse_r d, \\rd \n\t" -+ "parse_r j, \\rj \n\t" -+ "parse_r k, \\rk \n\t" -+ ".word ((0b00111000010110100 << 15) | (k << 10) | (j << 5) | d) \n\t" -+ ".endm \n\t" -+ -+ ".macro amcas_db_w rd, rk, rj \n\t" -+ "parse_r d, \\rd \n\t" -+ "parse_r j, \\rj \n\t" -+ "parse_r k, \\rk \n\t" -+ ".word ((0b00111000010110110 << 15) | (k << 10) | (j << 5) | d) \n\t" -+ ".endm \n\t" -+ -+ ".macro amcas_db_d rd, rk, rj \n\t" -+ "parse_r d, \\rd \n\t" -+ "parse_r j, \\rj \n\t" -+ "parse_r k, \\rk \n\t" -+ ".word ((0b00111000010110111 << 15) | (k << 10) | (j << 5) | d) \n\t" -+ ".endm \n\t" -+ ); -+#endif /* __AMCAS_ASM_H__ */ diff --git a/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/assembler_linux_loongarch.cpp new file mode 100644 index 00000000000..30719a0340b @@ -71490,13 +72327,13 @@ index 00000000000..30719a0340b + */ diff --git a/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp new file mode 100644 -index 00000000000..bb820b5e5ae +index 00000000000..f0c7a7e3a5d --- /dev/null +++ b/src/hotspot/os_cpu/linux_loongarch/atomic_linux_loongarch.hpp -@@ -0,0 +1,361 @@ +@@ -0,0 +1,499 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -71523,10 +72360,146 @@ index 00000000000..bb820b5e5ae +#define OS_CPU_LINUX_LOONGARCH_ATOMIC_LINUX_LOONGARCH_HPP + +#include "runtime/vm_version.hpp" -+#include "amcas_asm.h" + +// Implementation of class atomic + ++#define AMCAS_MACRO asm volatile ( \ ++ ".ifndef _ASM_ASMMACRO_ \n\t" \ ++ ".set _ASM_ASMMACRO_, 1 \n\t" \ ++ ".macro parse_r var r \n\t" \ ++ "\\var = -1 \n\t" \ ++ ".ifc \\r, $r0 \n\t" \ ++ "\\var = 0 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r1 \n\t" \ ++ "\\var = 1 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r2 \n\t" \ ++ "\\var = 2 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r3 \n\t" \ ++ "\\var = 3 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r4 \n\t" \ ++ "\\var = 4 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r5 \n\t" \ ++ "\\var = 5 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r6 \n\t" \ ++ "\\var = 6 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r7 \n\t" \ ++ "\\var = 7 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r8 \n\t" \ ++ "\\var = 8 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r9 \n\t" \ ++ "\\var = 9 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r10 \n\t" \ ++ "\\var = 10 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r11 \n\t" \ ++ "\\var = 11 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r12 \n\t" \ ++ "\\var = 12 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r13 \n\t" \ ++ "\\var = 13 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r14 \n\t" \ ++ "\\var = 14 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r15 \n\t" \ ++ "\\var = 15 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r16 \n\t" \ ++ "\\var = 16 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r17 \n\t" \ ++ "\\var = 17 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r18 \n\t" \ ++ "\\var = 18 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r19 \n\t" \ ++ "\\var = 19 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r20 \n\t" \ ++ "\\var = 20 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r21 \n\t" \ ++ "\\var = 21 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r22 \n\t" \ ++ "\\var = 22 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r23 \n\t" \ ++ "\\var = 23 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r24 \n\t" \ ++ "\\var = 24 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r25 \n\t" \ ++ "\\var = 25 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r26 \n\t" \ ++ "\\var = 26 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r27 \n\t" \ ++ "\\var = 27 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r28 \n\t" \ ++ "\\var = 28 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r29 \n\t" \ ++ "\\var = 29 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r30 \n\t" \ ++ "\\var = 30 \n\t" \ ++ ".endif \n\t" \ ++ ".ifc \\r, $r31 \n\t" \ ++ "\\var = 31 \n\t" \ ++ ".endif \n\t" \ ++ ".iflt \\var \n\t" \ ++ ".endif \n\t" \ ++ ".endm \n\t" \ ++ ".macro amcas_w rd, rk, rj \n\t" \ ++ "parse_r d, \\rd \n\t" \ ++ "parse_r j, \\rj \n\t" \ ++ "parse_r k, \\rk \n\t" \ ++ ".word ((0b00111000010110010 << 15) | (k << 10) | (j << 5) | d) \n\t" \ ++ ".endm \n\t" \ ++ ".macro amcas_d rd, rk, rj \n\t" \ ++ "parse_r d, \\rd \n\t" \ ++ "parse_r j, \\rj \n\t" \ ++ "parse_r k, \\rk \n\t" \ ++ ".word ((0b00111000010110011 << 15) | (k << 10) | (j << 5) | d) \n\t" \ ++ ".endm \n\t" \ ++ ".macro amcas_db_b rd, rk, rj \n\t" \ ++ "parse_r d, \\rd \n\t" \ ++ "parse_r j, \\rj \n\t" \ ++ "parse_r k, \\rk \n\t" \ ++ ".word ((0b00111000010110100 << 15) | (k << 10) | (j << 5) | d) \n\t" \ ++ ".endm \n\t" \ ++ ".macro amcas_db_w rd, rk, rj \n\t" \ ++ "parse_r d, \\rd \n\t" \ ++ "parse_r j, \\rj \n\t" \ ++ "parse_r k, \\rk \n\t" \ ++ ".word ((0b00111000010110110 << 15) | (k << 10) | (j << 5) | d) \n\t" \ ++ ".endm \n\t" \ ++ ".macro amcas_db_d rd, rk, rj \n\t" \ ++ "parse_r d, \\rd \n\t" \ ++ "parse_r j, \\rj \n\t" \ ++ "parse_r k, \\rk \n\t" \ ++ ".word ((0b00111000010110111 << 15) | (k << 10) | (j << 5) | d) \n\t" \ ++ ".endm \n\t" \ ++ ".endif \n\t" \ ++ ); ++ +template +struct Atomic::PlatformAdd { + template @@ -71663,6 +72636,7 @@ index 00000000000..bb820b5e5ae + T prev, temp; + + if (UseAMCAS) { ++ AMCAS_MACRO + switch (order) { + case memory_order_relaxed: + asm volatile ( @@ -71746,6 +72720,7 @@ index 00000000000..bb820b5e5ae + T prev, temp; + + if (UseAMCAS) { ++ AMCAS_MACRO + switch (order) { + case memory_order_relaxed: + asm volatile ( @@ -72421,13 +73396,13 @@ index 00000000000..2d096943ae8 +#endif // OS_CPU_LINUX_LOONGARCH_ORDERACCESS_LINUX_LOONGARCH_HPP diff --git a/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp new file mode 100644 -index 00000000000..31bfcba8db6 +index 00000000000..39ce20cd539 --- /dev/null +++ b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp -@@ -0,0 +1,491 @@ +@@ -0,0 +1,490 @@ +/* + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2015, 2024, Loongson Technology. 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 @@ -72455,7 +73430,6 @@ index 00000000000..31bfcba8db6 +#include "classfile/classLoader.hpp" +#include "classfile/systemDictionary.hpp" +#include "classfile/vmSymbols.hpp" -+#include "code/icBuffer.hpp" +#include "code/vtableStubs.hpp" +#include "interpreter/interpreter.hpp" +#include "memory/allocation.inline.hpp" @@ -72666,15 +73640,15 @@ index 00000000000..31bfcba8db6 + // here if the underlying file has been truncated. + // Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob(pc); -+ CompiledMethod* nm = (cb != nullptr) ? cb->as_compiled_method_or_null() : nullptr; ++ nmethod* nm = (cb != nullptr) ? cb->as_nmethod_or_null() : nullptr; +#ifdef PRINT_SIGNAL_HANDLE + tty->print("cb = %lx, nm = %lx\n", cb, nm); +#endif -+ bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc)); -+ if ((nm != nullptr && nm->has_unsafe_access()) || is_unsafe_arraycopy) { ++ bool is_unsafe_memory_access = (thread->doing_unsafe_access() && UnsafeMemoryAccess::contains_pc(pc)); ++ if ((nm != nullptr && nm->has_unsafe_access()) || is_unsafe_memory_access) { + address next_pc = pc + NativeInstruction::nop_instruction_size; -+ if (is_unsafe_arraycopy) { -+ next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); ++ if (is_unsafe_memory_access) { ++ next_pc = UnsafeMemoryAccess::page_error_continue_pc(pc); + } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } @@ -72720,8 +73694,8 @@ index 00000000000..31bfcba8db6 + tty->print_cr("SIGBUS in vm thread \n"); +#endif + address next_pc = pc + NativeInstruction::nop_instruction_size; -+ if (UnsafeCopyMemory::contains_pc(pc)) { -+ next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); ++ if (UnsafeMemoryAccess::contains_pc(pc)) { ++ next_pc = UnsafeMemoryAccess::page_error_continue_pc(pc); + } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } @@ -73015,14 +73989,14 @@ index 00000000000..5fe74ccd97c +#endif // OS_CPU_LINUX_LOONGARCH_PREFETCH_LINUX_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/os_cpu/linux_loongarch/safefetch_linux_loongarch64.S b/src/hotspot/os_cpu/linux_loongarch/safefetch_linux_loongarch64.S new file mode 100644 -index 00000000000..fdc6da358e5 +index 00000000000..170b848d1bc --- /dev/null +++ b/src/hotspot/os_cpu/linux_loongarch/safefetch_linux_loongarch64.S -@@ -0,0 +1,56 @@ +@@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 SAP SE. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2024, Loongson Technology. 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 @@ -73045,22 +74019,17 @@ index 00000000000..fdc6da358e5 + * + */ + -+ .globl SafeFetchN_impl -+ .globl _SafeFetchN_fault -+ .globl _SafeFetchN_continuation -+ .globl SafeFetch32_impl -+ .globl _SafeFetch32_fault -+ .globl _SafeFetch32_continuation ++#include "defs.S.inc" + + # Support for int SafeFetch32(int* address, int defaultval); + # + # a0 : address + # a1 : defaultval -+SafeFetch32_impl: -+_SafeFetch32_fault: ++DECLARE_FUNC(SafeFetch32_impl): ++DECLARE_FUNC(_SafeFetch32_fault): + ld.w $r4, $r4, 0 + jr $r1 -+_SafeFetch32_continuation: ++DECLARE_FUNC(_SafeFetch32_continuation): + or $r4, $r5, $r0 + jr $r1 + @@ -73068,11 +74037,11 @@ index 00000000000..fdc6da358e5 + # + # a0 : address + # a1 : defaultval -+SafeFetchN_impl: -+_SafeFetchN_fault: ++DECLARE_FUNC(SafeFetchN_impl): ++DECLARE_FUNC(_SafeFetchN_fault): + ld.d $r4, $r4, 0 + jr $r1 -+_SafeFetchN_continuation: ++DECLARE_FUNC(_SafeFetchN_continuation): + or $r4, $r5, $r0 + jr $r1 diff --git a/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp b/src/hotspot/os_cpu/linux_loongarch/vmStructs_linux_loongarch.hpp @@ -73237,8 +74206,33 @@ index 00000000000..3711a7036a1 + HWCAP_LOONGARCH_LBT_ARM | + HWCAP_LOONGARCH_LBT_MIPS); +} +diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp +index f084f506bf5..05a791db8ab 100644 +--- a/src/hotspot/share/adlc/archDesc.cpp ++++ b/src/hotspot/share/adlc/archDesc.cpp +@@ -22,6 +22,11 @@ + // + // + ++/* ++ * This file has been modified by Loongson Technology in 2024. These ++ * modifications are Copyright (c) 2024, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ + + // archDesc.cpp - Internal format for architecture definition + #include +@@ -756,7 +761,7 @@ bool ArchDesc::check_usage() { + callback.do_form_by_name("vecA"); + callback.do_form_by_name("vecD"); + callback.do_form_by_name("vecX"); +-#elif defined(IA32) || defined(AMD64) ++#elif defined(IA32) || defined(AMD64) || defined(LOONGARCH64) + callback.do_form_by_name("vecS"); + callback.do_form_by_name("vecD"); + callback.do_form_by_name("vecX"); diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp -index 8e2366e5d09..38e5fd7b2c6 100644 +index be97547f8ce..8cc9b9af0ed 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -22,6 +22,12 @@ @@ -73254,7 +74248,7 @@ index 8e2366e5d09..38e5fd7b2c6 100644 // FORMS.CPP - Definitions for ADL Parser Forms Classes #include "adlc.hpp" -@@ -4174,6 +4180,7 @@ bool MatchRule::is_ideal_membar() const { +@@ -4272,6 +4278,7 @@ bool MatchRule::is_ideal_membar() const { !strcmp(_opType,"MemBarVolatile") || !strcmp(_opType,"MemBarCPUOrder") || !strcmp(_opType,"MemBarStoreStore") || @@ -73263,7 +74257,7 @@ index 8e2366e5d09..38e5fd7b2c6 100644 } diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp -index bdbeb39f89a..c84f830eee7 100644 +index 897e2b6470d..4d07492e6fc 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -44,6 +44,12 @@ @@ -73271,8 +74265,8 @@ index bdbeb39f89a..c84f830eee7 100644 #include "utilities/macros.hpp" +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2024, These ++ * modifications are Copyright (c) 2022, 2024, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + @@ -73288,8 +74282,17 @@ index bdbeb39f89a..c84f830eee7 100644 case vmIntrinsics::_updateBytesCRC32C: case vmIntrinsics::_updateDirectByteBufferCRC32C: #endif +@@ -235,7 +241,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { + case vmIntrinsics::_counterTime: + #endif + case vmIntrinsics::_getObjectSize: +-#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) ++#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(LOONGARCH64) + case vmIntrinsics::_clone: + #endif + break; diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp -index dee208c11be..c147ee8f66a 100644 +index 6ca5b1bd136..208313ead0d 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -22,6 +22,12 @@ @@ -73297,15 +74300,24 @@ index dee208c11be..c147ee8f66a 100644 */ +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2024, These ++ * modifications are Copyright (c) 2022, 2024, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + #include "precompiled.hpp" #include "c1/c1_CodeStubs.hpp" #include "c1/c1_InstructionPrinter.hpp" -@@ -491,6 +497,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { +@@ -351,7 +357,7 @@ LIR_OpArrayCopy::LIR_OpArrayCopy(LIR_Opr src, LIR_Opr src_pos, LIR_Opr dst, LIR_ + , _tmp(tmp) + , _expected_type(expected_type) + , _flags(flags) { +-#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) ++#if defined(X86) || defined(AARCH64) || defined(S390) || defined(RISCV) || defined(PPC64) || defined(LOONGARCH64) + if (expected_type != nullptr && flags == 0) { + _stub = nullptr; + } else { +@@ -497,6 +503,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { assert(opConvert->_info == nullptr, "must be"); if (opConvert->_opr->is_valid()) do_input(opConvert->_opr); if (opConvert->_result->is_valid()) do_output(opConvert->_result); @@ -73313,7 +74325,7 @@ index dee208c11be..c147ee8f66a 100644 do_stub(opConvert->_stub); break; -@@ -1101,7 +1108,7 @@ LIR_List::LIR_List(Compilation* compilation, BlockBegin* block) +@@ -1110,7 +1117,7 @@ LIR_List::LIR_List(Compilation* compilation, BlockBegin* block) , _file(nullptr) , _line(0) #endif @@ -73322,7 +74334,7 @@ index dee208c11be..c147ee8f66a 100644 , _cmp_opr1(LIR_OprFact::illegalOpr) , _cmp_opr2(LIR_OprFact::illegalOpr) #endif -@@ -1122,7 +1129,7 @@ void LIR_List::set_file_and_line(const char * file, int line) { +@@ -1131,7 +1138,7 @@ void LIR_List::set_file_and_line(const char * file, int line) { } #endif @@ -73331,7 +74343,7 @@ index dee208c11be..c147ee8f66a 100644 void LIR_List::set_cmp_oprs(LIR_Op* op) { switch (op->code()) { case lir_cmp: -@@ -1151,7 +1158,7 @@ void LIR_List::set_cmp_oprs(LIR_Op* op) { +@@ -1160,7 +1167,7 @@ void LIR_List::set_cmp_oprs(LIR_Op* op) { break; #if INCLUDE_ZGC case lir_xloadbarrier_test: @@ -73340,7 +74352,7 @@ index dee208c11be..c147ee8f66a 100644 _cmp_opr2 = LIR_OprFact::intConst(0); break; #endif -@@ -1406,11 +1413,12 @@ void LIR_List::unsigned_shift_right(LIR_Opr value, LIR_Opr count, LIR_Opr dst, L +@@ -1416,11 +1423,12 @@ void LIR_List::unsigned_shift_right(LIR_Opr value, LIR_Opr count, LIR_Opr dst, L tmp)); } @@ -73355,7 +74367,7 @@ index dee208c11be..c147ee8f66a 100644 } void LIR_List::lock_object(LIR_Opr hdr, LIR_Opr obj, LIR_Opr lock, LIR_Opr scratch, CodeStub* stub, CodeEmitInfo* info) { -@@ -1927,6 +1935,9 @@ void LIR_OpConvert::print_instr(outputStream* out) const { +@@ -1937,6 +1945,9 @@ void LIR_OpConvert::print_instr(outputStream* out) const { print_bytecode(out, bytecode()); in_opr()->print(out); out->print(" "); result_opr()->print(out); out->print(" "); @@ -73366,7 +74378,7 @@ index dee208c11be..c147ee8f66a 100644 void LIR_OpConvert::print_bytecode(outputStream* out, Bytecodes::Code code) { diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp -index 6f527135fbe..2e2910bdb5c 100644 +index c69d29f8d61..d0140c88f03 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -22,6 +22,12 @@ @@ -73403,7 +74415,7 @@ index 6f527135fbe..2e2910bdb5c 100644 virtual void emit_code(LIR_Assembler* masm); virtual LIR_OpConvert* as_OpConvert() { return this; } -@@ -2097,7 +2106,7 @@ class LIR_List: public CompilationResourceObj { +@@ -2100,7 +2109,7 @@ class LIR_List: public CompilationResourceObj { const char * _file; int _line; #endif @@ -73412,7 +74424,7 @@ index 6f527135fbe..2e2910bdb5c 100644 LIR_Opr _cmp_opr1; LIR_Opr _cmp_opr2; #endif -@@ -2113,7 +2122,7 @@ class LIR_List: public CompilationResourceObj { +@@ -2116,7 +2125,7 @@ class LIR_List: public CompilationResourceObj { } #endif // PRODUCT @@ -73421,7 +74433,7 @@ index 6f527135fbe..2e2910bdb5c 100644 set_cmp_oprs(op); // lir_cmp set cmp oprs only on riscv if (op->code() == lir_cmp) return; -@@ -2135,7 +2144,7 @@ class LIR_List: public CompilationResourceObj { +@@ -2138,7 +2147,7 @@ class LIR_List: public CompilationResourceObj { void set_file_and_line(const char * file, int line); #endif @@ -73430,7 +74442,7 @@ index 6f527135fbe..2e2910bdb5c 100644 void set_cmp_oprs(LIR_Op* op); #endif -@@ -2228,7 +2237,9 @@ class LIR_List: public CompilationResourceObj { +@@ -2231,7 +2240,9 @@ class LIR_List: public CompilationResourceObj { void safepoint(LIR_Opr tmp, CodeEmitInfo* info) { append(new LIR_Op1(lir_safepoint, tmp, info)); } void return_op(LIR_Opr result) { append(new LIR_OpReturn(result)); } @@ -73441,7 +74453,7 @@ index 6f527135fbe..2e2910bdb5c 100644 void logical_and (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_and, left, right, dst)); } void logical_or (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_or, left, right, dst)); } -@@ -2336,7 +2347,7 @@ class LIR_List: public CompilationResourceObj { +@@ -2339,7 +2350,7 @@ class LIR_List: public CompilationResourceObj { void unsigned_shift_right(LIR_Opr value, int count, LIR_Opr dst) { unsigned_shift_right(value, LIR_OprFact::intConst(count), dst, LIR_OprFact::illegalOpr); } void lcmp2int(LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_cmp_l2i, left, right, dst)); } @@ -73451,7 +74463,7 @@ index 6f527135fbe..2e2910bdb5c 100644 void call_runtime_leaf(address routine, LIR_Opr tmp, LIR_Opr result, LIR_OprList* arguments) { append(new LIR_OpRTCall(routine, tmp, result, arguments)); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp -index 7e46f9d5603..97f98d5a5e0 100644 +index a4d955e52a0..79d0d03e961 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -22,6 +22,12 @@ @@ -73537,8 +74549,65 @@ index 7e46f9d5603..97f98d5a5e0 100644 } } } +diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp +index e60495d1f47..be9f5530ce4 100644 +--- a/src/hotspot/share/classfile/vmIntrinsics.cpp ++++ b/src/hotspot/share/classfile/vmIntrinsics.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/vmIntrinsics.hpp" + #include "classfile/vmSymbols.hpp" +@@ -461,6 +467,10 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { + case vmIntrinsics::_galoisCounterMode_AESCrypt: + if (!UseAESIntrinsics) return true; + break; ++ case vmIntrinsics::_descrypt_encryptBlock: ++ case vmIntrinsics::_descrypt_decryptBlock: ++ if (!UseDESIntrinsics) return true; ++ break; + case vmIntrinsics::_md5_implCompress: + if (!UseMD5Intrinsics) return true; + break; +diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp +index 7a5c2ee47bb..3514c1155e5 100644 +--- a/src/hotspot/share/classfile/vmIntrinsics.hpp ++++ b/src/hotspot/share/classfile/vmIntrinsics.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_CLASSFILE_VMINTRINSICS_HPP + #define SHARE_CLASSFILE_VMINTRINSICS_HPP + +@@ -499,6 +505,11 @@ class methodHandle; + do_name(gcm_crypt_name, "implGCMCrypt0") \ + do_signature(aes_gcm_signature, "([BII[BI[BILcom/sun/crypto/provider/GCTR;Lcom/sun/crypto/provider/GHASH;)I") \ + \ ++ /* support for com.sun.crypto.provider.DESCrypt and some of its callers */ \ ++ do_class(com_sun_crypto_provider_descrypt, "com/sun/crypto/provider/DESCrypt") \ ++ do_intrinsic(_descrypt_encryptBlock, com_sun_crypto_provider_descrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ ++ do_intrinsic(_descrypt_decryptBlock, com_sun_crypto_provider_descrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ ++ \ + /* support for sun.security.provider.MD5 */ \ + do_class(sun_security_provider_md5, "sun/security/provider/MD5") \ + do_intrinsic(_md5_implCompress, sun_security_provider_md5, implCompress_name, implCompress_signature, F_R) \ diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp -index eed3dc8e787..c8b58dd459c 100644 +index 5a54426d6a4..d23c220b3e0 100644 --- a/src/hotspot/share/code/vtableStubs.cpp +++ b/src/hotspot/share/code/vtableStubs.cpp @@ -22,6 +22,12 @@ @@ -73567,7 +74636,7 @@ index eed3dc8e787..c8b58dd459c 100644 #else // These values are good for the non-PRODUCT case (when tracing can be switched on). diff --git a/src/hotspot/share/gc/g1/g1Arguments.cpp b/src/hotspot/share/gc/g1/g1Arguments.cpp -index b8a7c677f7f..e02033a1ff5 100644 +index a62eb994486..8dd73f47b57 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -23,6 +23,12 @@ @@ -73583,7 +74652,7 @@ index b8a7c677f7f..e02033a1ff5 100644 #include "precompiled.hpp" #include "cds/cdsConfig.hpp" #include "gc/g1/g1Arguments.hpp" -@@ -168,6 +174,20 @@ void G1Arguments::initialize_card_set_configuration() { +@@ -162,6 +168,20 @@ void G1Arguments::initialize_card_set_configuration() { void G1Arguments::initialize() { GCArguments::initialize(); assert(UseG1GC, "Error"); @@ -73605,7 +74674,7 @@ index b8a7c677f7f..e02033a1ff5 100644 if (ParallelGCThreads == 0) { assert(!FLAG_IS_DEFAULT(ParallelGCThreads), "The default value for ParallelGCThreads should not be 0."); diff --git a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp -index 7f666c0f497..a456386443e 100644 +index a164fa34929..81f38751e85 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp @@ -22,6 +22,12 @@ @@ -73632,7 +74701,7 @@ index 7f666c0f497..a456386443e 100644 } diff --git a/src/hotspot/share/gc/parallel/parallelArguments.cpp b/src/hotspot/share/gc/parallel/parallelArguments.cpp -index 468dc7bdfaf..c331cbf2be6 100644 +index 313716752d5..dbb04b9f788 100644 --- a/src/hotspot/share/gc/parallel/parallelArguments.cpp +++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp @@ -23,6 +23,12 @@ @@ -73662,7 +74731,7 @@ index 468dc7bdfaf..c331cbf2be6 100644 // of the physical memory, up to a maximum of 1GB. FLAG_SET_DEFAULT(ParallelGCThreads, diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp -index adf0527681b..a1a76917f39 100644 +index 9ce4f30c436..21d923a2101 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -22,6 +22,12 @@ @@ -73678,7 +74747,7 @@ index adf0527681b..a1a76917f39 100644 #include "precompiled.hpp" #include "code/codeCache.hpp" #include "code/nmethod.hpp" -@@ -158,7 +164,7 @@ void BarrierSetNMethod::arm_all_nmethods() { +@@ -152,7 +158,7 @@ void BarrierSetNMethod::arm_all_nmethods() { BarrierSetNMethodArmClosure cl(_current_phase); Threads::threads_do(&cl); @@ -73688,7 +74757,7 @@ index adf0527681b..a1a76917f39 100644 // the counter won't overflow. BarrierSetAssembler::clear_patching_epoch(); diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp -index 41bd15ab000..508e37fa2c4 100644 +index 59e02452044..56f2a4b03a4 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -22,6 +22,12 @@ @@ -73702,9 +74771,9 @@ index 41bd15ab000..508e37fa2c4 100644 + */ + #include "precompiled.hpp" - #include "gc/shared/tlab_globals.hpp" - #include "gc/shared/c2/barrierSetC2.hpp" -@@ -263,6 +269,8 @@ class C2AccessFence: public StackObj { + #include "code/vmreg.inline.hpp" + #include "gc/shared/barrierSet.hpp" +@@ -316,6 +322,8 @@ class C2AccessFence: public StackObj { bool is_volatile = (decorators & MO_SEQ_CST) != 0; bool is_acquire = (decorators & MO_ACQUIRE) != 0; @@ -73713,7 +74782,7 @@ index 41bd15ab000..508e37fa2c4 100644 // If reference is volatile, prevent following volatiles ops from // floating up before the volatile access. -@@ -296,6 +304,13 @@ class C2AccessFence: public StackObj { +@@ -349,6 +357,13 @@ class C2AccessFence: public StackObj { assert(_leading_membar == nullptr || support_IRIW_for_not_multiple_copy_atomic_cpu, "no leading membar expected"); Node* mb = kit->insert_mem_bar(Op_MemBarAcquire, n); mb->as_MemBar()->set_trailing_load(); @@ -73727,6 +74796,36 @@ index 41bd15ab000..508e37fa2c4 100644 } } } +diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +index dbb45995698..1f37818e14e 100644 +--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp ++++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +@@ -23,6 +23,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + + #include "classfile/javaClasses.hpp" +@@ -433,6 +439,12 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) { + "cipherBlockChaining_decryptAESCrypt", + { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, + { TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, ++ "descrypt_encryptBlock", ++ { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, ++ { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, ++ "descrypt_decryptBlock", ++ { { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad }, ++ { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, + "shenandoah_clone_barrier", + { { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone}, + { -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} }, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index d9b28c1bb4d..b6435ac7334 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -73830,7 +74929,7 @@ index f917a6c3e7b..a851a673f98 100644 ZStoreBarrierEntry _buffer[_buffer_length]; diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp -index 70439459d35..a9ebc001900 100644 +index dc5f2f5b637..cd65c595a6b 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -22,6 +22,12 @@ @@ -73846,7 +74945,7 @@ index 70439459d35..a9ebc001900 100644 #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/symbolTable.hpp" -@@ -1461,7 +1467,7 @@ JRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* current, Met +@@ -1451,7 +1457,7 @@ JRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* current, Met // preparing the same method will be sure to see non-null entry & mirror. JRT_END @@ -73910,28 +75009,6 @@ index bcccff2fe82..5c836ab5114 100644 #ifdef ARM32 void generate_math_runtime_call(AbstractInterpreter::MethodKind kind); -diff --git a/src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp b/src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp -index c26592763d4..da669ee4354 100644 ---- a/src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp -+++ b/src/hotspot/share/jfr/support/jfrNativeLibraryLoadEvent.cpp -@@ -105,13 +105,15 @@ static void commit(HelperType& helper) { - assert(thread != nullptr, "invariant"); - if (thread->is_Java_thread()) { - JavaThread* jt = JavaThread::cast(thread); -- if (jt->thread_state() != _thread_in_vm) { -- assert(jt->thread_state() == _thread_in_native, "invariant"); -+ if (jt->thread_state() == _thread_in_native) { - // For a JavaThread to take a JFR stacktrace, it must be in _thread_in_vm. Can safepoint here. - ThreadInVMfromNative transition(jt); - event.commit(); - return; - } -+ // If a thread comes here still _thread_in_Java, which can happen for example -+ // when loading the disassembler library in response to traps in JIT code - all is ok. -+ // Since there is no ljf, an event will be committed without a stacktrace. - } - event.commit(); - } diff --git a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp index 7661b35863c..ad281cad645 100644 --- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -73958,8 +75035,33 @@ index 7661b35863c..ad281cad645 100644 return false; #else #warning "Unconfigured platform" +diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +index a2ba0f2b3e5..01f7139e185 100644 +--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp ++++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +@@ -21,6 +21,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + // no precompiled headers + #ifdef COMPILER1 + #include "c1/c1_Compiler.hpp" +@@ -323,6 +329,7 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) { + do_uintx_flag(TLABWasteIncrement) \ + do_intx_flag(TypeProfileWidth) \ + do_bool_flag(UseAESIntrinsics) \ ++ do_bool_flag(UseDESIntrinsics) \ + X86_ONLY(do_int_flag(UseAVX)) \ + do_bool_flag(UseCRC32Intrinsics) \ + do_bool_flag(UseAdler32Intrinsics) \ diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp -index bac9a786fd9..0bb983e6246 100644 +index f0ecc5af7d2..f59bc560dc7 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -22,6 +22,12 @@ @@ -73967,15 +75069,29 @@ index bac9a786fd9..0bb983e6246 100644 */ +/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2022, 2023, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + #include "precompiled.hpp" #include "code/codeCache.hpp" - #include "compiler/compileBroker.hpp" -@@ -871,6 +877,17 @@ + #include "code/compiledIC.hpp" +@@ -354,9 +360,13 @@ + static_field(StubRoutines, _electronicCodeBook_decryptAESCrypt, address) \ + static_field(StubRoutines, _counterMode_AESCrypt, address) \ + static_field(StubRoutines, _galoisCounterMode_AESCrypt, address) \ ++ static_field(StubRoutines, _descrypt_encryptBlock, address) \ ++ static_field(StubRoutines, _descrypt_decryptBlock, address) \ + static_field(StubRoutines, _base64_encodeBlock, address) \ + static_field(StubRoutines, _base64_decodeBlock, address) \ + static_field(StubRoutines, _ghash_processBlocks, address) \ ++ static_field(StubRoutines, _descrypt_encryptBlock, address) \ ++ static_field(StubRoutines, _descrypt_decryptBlock, address) \ + static_field(StubRoutines, _md5_implCompress, address) \ + static_field(StubRoutines, _md5_implCompressMB, address) \ + static_field(StubRoutines, _chacha20Block, address) \ +@@ -880,6 +890,17 @@ #endif @@ -73994,7 +75110,7 @@ index bac9a786fd9..0bb983e6246 100644 #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp -index c7590861032..c192d19e849 100644 +index 54f1423fd1c..4074424c695 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -22,6 +22,12 @@ @@ -74010,7 +75126,7 @@ index c7590861032..c192d19e849 100644 #ifndef SHARE_OOPS_STACKCHUNKOOP_INLINE_HPP #define SHARE_OOPS_STACKCHUNKOOP_INLINE_HPP -@@ -336,7 +342,7 @@ inline void stackChunkOopDesc::copy_from_stack_to_chunk(intptr_t* from, intptr_t +@@ -337,7 +343,7 @@ inline void stackChunkOopDesc::copy_from_stack_to_chunk(intptr_t* from, intptr_t assert(to >= start_address(), "Chunk underflow"); assert(to + size <= end_address(), "Chunk overflow"); @@ -74019,7 +75135,7 @@ index c7590861032..c192d19e849 100644 // Suppress compilation warning-as-error on unimplemented architectures // that stub out arch-specific methods. Some compilers are smart enough // to figure out the argument is always null and then warn about it. -@@ -355,7 +361,7 @@ inline void stackChunkOopDesc::copy_from_chunk_to_stack(intptr_t* from, intptr_t +@@ -356,7 +362,7 @@ inline void stackChunkOopDesc::copy_from_chunk_to_stack(intptr_t* from, intptr_t assert(from >= start_address(), ""); assert(from + size <= end_address(), ""); @@ -74028,8 +75144,34 @@ index c7590861032..c192d19e849 100644 // Suppress compilation warning-as-error on unimplemented architectures // that stub out arch-specific methods. Some compilers are smart enough // to figure out the argument is always null and then warn about it. +diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp +index c5e17478477..e6cf9c1abbd 100644 +--- a/src/hotspot/share/opto/c2compiler.cpp ++++ b/src/hotspot/share/opto/c2compiler.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/vmClasses.hpp" + #include "compiler/compilationMemoryStatistic.hpp" +@@ -769,6 +775,8 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { + case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: + case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: + case vmIntrinsics::_counterMode_AESCrypt: ++ case vmIntrinsics::_descrypt_encryptBlock: ++ case vmIntrinsics::_descrypt_decryptBlock: + case vmIntrinsics::_md5_implCompress: + case vmIntrinsics::_sha_implCompress: + case vmIntrinsics::_sha2_implCompress: diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp -index 7d1a2cd1db0..f936dd8e748 100644 +index db6cb817d77..9ddc18b0afc 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -22,6 +22,12 @@ @@ -74054,7 +75196,7 @@ index 7d1a2cd1db0..f936dd8e748 100644 macro(MinI) macro(MinL) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp -index 8a5e98eda92..a572e02bb9a 100644 +index 25c7ced8aeb..1ca04148e5b 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -22,6 +22,12 @@ @@ -74070,7 +75212,7 @@ index 8a5e98eda92..a572e02bb9a 100644 #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" -@@ -3772,6 +3778,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f +@@ -3816,6 +3822,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f n->set_req(MemBarNode::Precedent, top()); } break; @@ -74078,8 +75220,163 @@ index 8a5e98eda92..a572e02bb9a 100644 case Op_MemBarAcquire: { if (n->as_MemBar()->trailing_load() && n->req() > MemBarNode::Precedent) { // At parse time, the trailing MemBarAcquire for a volatile load +diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp +index 18a45f11117..97162418511 100644 +--- a/src/hotspot/share/opto/escape.cpp ++++ b/src/hotspot/share/opto/escape.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "ci/bcEscapeAnalyzer.hpp" + #include "compiler/compileLog.hpp" +@@ -2182,6 +2188,8 @@ void ConnectionGraph::process_call_arguments(CallNode *call) { + strcmp(call->as_CallLeaf()->_name, "electronicCodeBook_decryptAESCrypt") == 0 || + strcmp(call->as_CallLeaf()->_name, "counterMode_AESCrypt") == 0 || + strcmp(call->as_CallLeaf()->_name, "galoisCounterMode_AESCrypt") == 0 || ++ strcmp(call->as_CallLeaf()->_name, "descrypt_encryptBlock") == 0 || ++ strcmp(call->as_CallLeaf()->_name, "descrypt_decryptBlock") == 0 || + strcmp(call->as_CallLeaf()->_name, "poly1305_processBlocks") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_montgomeryMult_P256") == 0 || + strcmp(call->as_CallLeaf()->_name, "intpoly_assign") == 0 || +diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp +index fead57b0901..983a806def2 100644 +--- a/src/hotspot/share/opto/library_call.cpp ++++ b/src/hotspot/share/opto/library_call.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "asm/macroAssembler.hpp" + #include "ci/ciUtilities.inline.hpp" +@@ -596,6 +602,9 @@ bool LibraryCallKit::try_to_inline(int predicate) { + case vmIntrinsics::_galoisCounterMode_AESCrypt: + return inline_galoisCounterMode_AESCrypt(); + ++ case vmIntrinsics::_descrypt_encryptBlock: ++ case vmIntrinsics::_descrypt_decryptBlock: return inline_descrypt_Block(intrinsic_id()); ++ + case vmIntrinsics::_md5_implCompress: + case vmIntrinsics::_sha_implCompress: + case vmIntrinsics::_sha2_implCompress: +@@ -7418,6 +7427,75 @@ bool LibraryCallKit::inline_ghash_processBlocks() { + return true; + } + ++//------------------------------get_key_start_from_descrypt_object----------------------- ++Node * LibraryCallKit::get_key_start_from_descrypt_object(Node *descrypt_object) { ++ Node* objDESCryptKey = load_field_from_object(descrypt_object, "expandedKey", "[B"); ++ assert (objDESCryptKey != NULL, "wrong version of com.sun.crypto.provider.DESCrypt"); ++ if (objDESCryptKey == NULL) return (Node *) NULL; ++ ++ // now have the array, need to get the start address of the K array ++ Node* k_start = array_element_address(objDESCryptKey, intcon(0), T_BYTE); ++ return k_start; ++} ++ ++//------------------------------inline_descrypt_Block----------------------- ++bool LibraryCallKit::inline_descrypt_Block(vmIntrinsics::ID id) { ++ address stubAddr = NULL; ++ const char *stubName; ++ ++ switch(id) { ++ case vmIntrinsics::_descrypt_encryptBlock: ++ stubAddr = StubRoutines::descrypt_encryptBlock(); ++ stubName = "descrypt_encryptBlock"; ++ break; ++ case vmIntrinsics::_descrypt_decryptBlock: ++ stubAddr = StubRoutines::descrypt_decryptBlock(); ++ stubName = "descrypt_decryptBlock"; ++ break; ++ default: ++ break; ++ } ++ if (stubAddr == NULL) return false; ++ ++ Node* descrypt_object = argument(0); ++ Node* src = argument(1); ++ Node* src_offset = argument(2); ++ Node* dest = argument(3); ++ Node* dest_offset = argument(4); ++ ++ src = must_be_not_null(src, true); ++ dest = must_be_not_null(dest, true); ++ ++ // (1) src and dest are arrays. ++ const Type* src_type = src->Value(&_gvn); ++ const Type* dest_type = dest->Value(&_gvn); ++ const TypeAryPtr* top_src = src_type->isa_aryptr(); ++ const TypeAryPtr* top_dest = dest_type->isa_aryptr(); ++ assert (top_src != NULL && top_src->elem() != Type::BOTTOM && top_dest != NULL && top_dest->elem() != Type::BOTTOM, "args are strange"); ++ ++ // for the quick and dirty code we will skip all the checks. ++ // we are just trying to get the call to be generated. ++ Node* src_start = src; ++ Node* dest_start = dest; ++ if (src_offset != NULL || dest_offset != NULL) { ++ assert(src_offset != NULL && dest_offset != NULL, ""); ++ src_start = array_element_address(src, src_offset, T_BYTE); ++ dest_start = array_element_address(dest, dest_offset, T_BYTE); ++ } ++ ++ // now need to get the start of its expanded key array ++ // this requires a newer class file that has this array as littleEndian ints, otherwise we revert to java ++ Node* k_start = get_key_start_from_descrypt_object(descrypt_object); ++ if (k_start == NULL) return false; ++ ++ // Call the stub. ++ make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::descrypt_block_Type(), ++ stubAddr, stubName, TypePtr::BOTTOM, ++ src_start, dest_start, k_start); ++ ++ return true; ++} ++ + //------------------------------inline_chacha20Block + bool LibraryCallKit::inline_chacha20Block() { + address stubAddr; +diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp +index 313e8c39544..d356e8311f1 100644 +--- a/src/hotspot/share/opto/library_call.hpp ++++ b/src/hotspot/share/opto/library_call.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "ci/ciMethod.hpp" + #include "classfile/javaClasses.hpp" + #include "opto/callGenerator.hpp" +@@ -304,6 +310,8 @@ class LibraryCallKit : public GraphKit { + Node* inline_counterMode_AESCrypt_predicate(); + Node* get_key_start_from_aescrypt_object(Node* aescrypt_object); + bool inline_ghash_processBlocks(); ++ Node* get_key_start_from_descrypt_object(Node* descrypt_object); ++ bool inline_descrypt_Block(vmIntrinsics::ID id); + bool inline_chacha20Block(); + bool inline_base64_encodeBlock(); + bool inline_base64_decodeBlock(); diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp -index c402a240acb..de8f6835ae6 100644 +index 775764d0254..c4f70158a74 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -22,6 +22,12 @@ @@ -74095,7 +75392,7 @@ index c402a240acb..de8f6835ae6 100644 #include "precompiled.hpp" #include "classfile/javaClasses.hpp" #include "compiler/compileLog.hpp" -@@ -3327,6 +3333,7 @@ MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { +@@ -4093,6 +4099,7 @@ MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { case Op_MemBarReleaseLock: return new MemBarReleaseLockNode(C, atp, pn); case Op_MemBarVolatile: return new MemBarVolatileNode(C, atp, pn); case Op_MemBarCPUOrder: return new MemBarCPUOrderNode(C, atp, pn); @@ -74104,7 +75401,7 @@ index c402a240acb..de8f6835ae6 100644 case Op_Initialize: return new InitializeNode(C, atp, pn); default: ShouldNotReachHere(); return nullptr; diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp -index 85f4380188d..0ca6096e59f 100644 +index e0f5a437413..65241574207 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -22,6 +22,12 @@ @@ -74120,7 +75417,7 @@ index 85f4380188d..0ca6096e59f 100644 #ifndef SHARE_OPTO_MEMNODE_HPP #define SHARE_OPTO_MEMNODE_HPP -@@ -1292,6 +1298,14 @@ class MemBarCPUOrderNode: public MemBarNode { +@@ -1299,6 +1305,14 @@ class MemBarCPUOrderNode: public MemBarNode { virtual uint ideal_reg() const { return 0; } // not matched in the AD file }; @@ -74136,7 +75433,7 @@ index 85f4380188d..0ca6096e59f 100644 public: OnSpinWaitNode(Compile* C, int alias_idx, Node* precedent) diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp -index 9481b91ce39..e6fe6a706cc 100644 +index 60d1ca57e56..77bfe465b91 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -22,6 +22,12 @@ @@ -74144,30 +75441,30 @@ index 9481b91ce39..e6fe6a706cc 100644 */ +/* -+ * This file has been modified by Loongson Technology in 2022. These -+ * modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made ++ * This file has been modified by Loongson Technology in 2024. These ++ * modifications are Copyright (c) 2019, 2024, Loongson Technology, and are made + * available on the same license terms set forth above. + */ + #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" -@@ -1697,6 +1703,22 @@ void PhaseOutput::fill_buffer(CodeBuffer* cb, uint* blk_starts) { - DEBUG_ONLY(uint instr_offset = cb->insts_size()); - n->emit(*cb, C->regalloc()); - current_offset = cb->insts_size(); +@@ -1721,6 +1727,22 @@ void PhaseOutput::fill_buffer(C2_MacroAssembler* masm, uint* blk_starts) { + DEBUG_ONLY(uint instr_offset = masm->offset()); + n->emit(masm, C->regalloc()); + current_offset = masm->offset(); +#if defined(LOONGARCH) -+ if (!n->is_Proj() && (cb->insts()->end() != badAddress)) { ++ if (!n->is_Proj() && (masm->code()->insts()->end() != badAddress)) { + // For LOONGARCH, the first instruction of the previous node (usually a instruction sequence) sometime + // is not the instruction which access memory. adjust is needed. previous_offset points to the -+ // instruction which access memory. Instruction size is 4. cb->insts_size() and -+ // cb->insts()->end() are the location of current instruction. ++ // instruction which access memory. Instruction size is 4. masm->code()->insts_size() and ++ // masm->code()->insts()->end() are the location of current instruction. + int adjust = 4; -+ NativeInstruction* inst = (NativeInstruction*) (cb->insts()->end() - 4); ++ NativeInstruction* inst = (NativeInstruction*) (masm->code()->insts()->end() - 4); + if (inst->is_sync()) { + // a sync may be the last instruction, see store_B_immI_enc_sync + adjust += 4; -+ inst = (NativeInstruction*) (cb->insts()->end() - 8); ++ inst = (NativeInstruction*) (masm->code()->insts()->end() - 8); + } + previous_offset = current_offset - adjust; + } @@ -74175,8 +75472,77 @@ index 9481b91ce39..e6fe6a706cc 100644 // Above we only verified that there is enough space in the instruction section. // However, the instruction may emit stubs that cause code buffer expansion. +diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp +index f489c82484f..3df8eb3e3c4 100644 +--- a/src/hotspot/share/opto/runtime.cpp ++++ b/src/hotspot/share/opto/runtime.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "classfile/vmClasses.hpp" + #include "classfile/vmSymbols.hpp" +@@ -1102,6 +1108,26 @@ const TypeFunc* OptoRuntime::galoisCounterMode_aescrypt_Type() { + return TypeFunc::make(domain, range); + } + ++// for descrypt encrypt/decrypt operations, just three pointers returning void (length is constant) ++const TypeFunc* OptoRuntime::descrypt_block_Type() { ++ // create input type (domain) ++ int num_args = 3; ++ int argcnt = num_args; ++ const Type** fields = TypeTuple::fields(argcnt); ++ int argp = TypeFunc::Parms; ++ fields[argp++] = TypePtr::NOTNULL; // src ++ fields[argp++] = TypePtr::NOTNULL; // dest ++ fields[argp++] = TypePtr::NOTNULL; // k array ++ assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); ++ const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); ++ ++ // no result type needed ++ fields = TypeTuple::fields(1); ++ fields[TypeFunc::Parms+0] = NULL; // void ++ const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); ++ return TypeFunc::make(domain, range); ++} ++ + /* + * void implCompress(byte[] buf, int ofs) + */ +diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp +index e4cbdf2f0d0..a8a8f01628e 100644 +--- a/src/hotspot/share/opto/runtime.hpp ++++ b/src/hotspot/share/opto/runtime.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_OPTO_RUNTIME_HPP + #define SHARE_OPTO_RUNTIME_HPP + +@@ -277,6 +283,7 @@ class OptoRuntime : public AllStatic { + static const TypeFunc* electronicCodeBook_aescrypt_Type(); + static const TypeFunc* counterMode_aescrypt_Type(); + static const TypeFunc* galoisCounterMode_aescrypt_Type(); ++ static const TypeFunc* descrypt_block_Type(); + + static const TypeFunc* digestBase_implCompress_Type(bool is_sha3); + static const TypeFunc* digestBase_implCompressMB_Type(bool is_sha3); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index 250bef15869..1360e72dbbd 100644 +index 6c98f379db0..4ca385c534e 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -22,6 +22,12 @@ @@ -74192,7 +75558,7 @@ index 250bef15869..1360e72dbbd 100644 #include "precompiled.hpp" #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" -@@ -1844,14 +1850,14 @@ bool Arguments::check_vm_args_consistency() { +@@ -1834,14 +1840,14 @@ bool Arguments::check_vm_args_consistency() { } #endif @@ -74210,7 +75576,7 @@ index 250bef15869..1360e72dbbd 100644 jio_fprintf(defaultStream::error_stream(), "LockingMode == 0 (LM_MONITOR) is not fully implemented on this architecture\n"); diff --git a/src/hotspot/share/runtime/continuation.cpp b/src/hotspot/share/runtime/continuation.cpp -index 03c0af1a572..7e468def61d 100644 +index cd55b4a9cff..28098bcce25 100644 --- a/src/hotspot/share/runtime/continuation.cpp +++ b/src/hotspot/share/runtime/continuation.cpp @@ -22,6 +22,12 @@ @@ -74236,7 +75602,7 @@ index 03c0af1a572..7e468def61d 100644 #else frame sender = frame(); diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp -index 47906e81f11..3e9ac7a8502 100644 +index 77ec9642d48..875867bba1d 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -22,6 +22,12 @@ @@ -74252,7 +75618,7 @@ index 47906e81f11..3e9ac7a8502 100644 #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/vmSymbols.hpp" -@@ -808,7 +814,7 @@ frame FreezeBase::freeze_start_frame_yield_stub(frame f) { +@@ -799,7 +805,7 @@ frame FreezeBase::freeze_start_frame_yield_stub(frame f) { } frame FreezeBase::freeze_start_frame_safepoint_stub(frame f) { @@ -74261,7 +75627,7 @@ index 47906e81f11..3e9ac7a8502 100644 f.set_fp(f.real_fp()); // f.set_fp(*Frame::callee_link_address(f)); // ???? #else Unimplemented(); -@@ -866,7 +872,7 @@ inline freeze_result FreezeBase::recurse_freeze_java_frame(const frame& f, frame +@@ -857,7 +863,7 @@ inline freeze_result FreezeBase::recurse_freeze_java_frame(const frame& f, frame _freeze_size += fsize; NOT_PRODUCT(_frames++;) @@ -74270,7 +75636,7 @@ index 47906e81f11..3e9ac7a8502 100644 // We don't use FKind::frame_bottom(f) == _bottom_address because on x64 there's sometimes an extra word between // enterSpecial and an interpreted frame -@@ -1638,7 +1644,7 @@ static freeze_result is_pinned0(JavaThread* thread, oop cont_scope, bool safepoi +@@ -1630,7 +1636,7 @@ static freeze_result is_pinned0(JavaThread* thread, oop cont_scope, bool safepoi if (!safepoint) { f = f.sender(&map); // this is the yield frame } else { // safepoint yield @@ -74279,7 +75645,7 @@ index 47906e81f11..3e9ac7a8502 100644 f.set_fp(f.real_fp()); // Instead of this, maybe in ContinuationWrapper::set_last_frame always use the real_fp? #else Unimplemented(); -@@ -2279,8 +2285,8 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n +@@ -2269,8 +2275,8 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n // If we're the bottom-most thawed frame, we're writing to within one word from entrySP // (we might have one padding word for alignment) @@ -74290,6 +75656,33 @@ index 47906e81f11..3e9ac7a8502 100644 copy_from_chunk(from, to, sz); // copying good oops because we invoked barriers above +diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp +index 6f66a349595..b0f9e94bcb8 100644 +--- a/src/hotspot/share/runtime/globals.hpp ++++ b/src/hotspot/share/runtime/globals.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_RUNTIME_GLOBALS_HPP + #define SHARE_RUNTIME_GLOBALS_HPP + +@@ -321,6 +327,9 @@ const int ObjectAlignmentInBytes = 8; + product(bool, UseAESCTRIntrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for the paralleled version of AES/CTR crypto") \ + \ ++ product(bool, UseDESIntrinsics, false, DIAGNOSTIC, \ ++ "Use intrinsics for DES versions of crypto") \ ++ \ + product(bool, UseChaCha20Intrinsics, false, DIAGNOSTIC, \ + "Use intrinsics for the vectorized version of ChaCha20") \ + \ diff --git a/src/hotspot/share/runtime/javaThread.inline.hpp b/src/hotspot/share/runtime/javaThread.inline.hpp index 7b1ad7e17e1..c7a0246e375 100644 --- a/src/hotspot/share/runtime/javaThread.inline.hpp @@ -74326,7 +75719,7 @@ index 7b1ad7e17e1..c7a0246e375 100644 // Threads::create_vm() for size checks. Atomic::release_store(&_thread_state, s); diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp -index 2214713aa4b..462e3e8031b 100644 +index ba463231592..5ca112fa309 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -22,6 +22,12 @@ @@ -74342,7 +75735,7 @@ index 2214713aa4b..462e3e8031b 100644 #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/oopStorage.hpp" -@@ -356,6 +362,9 @@ bool ObjectMonitor::enter(JavaThread* current) { +@@ -404,6 +410,9 @@ bool ObjectMonitor::enter(JavaThread* current) { } assert(owner_raw() != current, "invariant"); @@ -74352,7 +75745,7 @@ index 2214713aa4b..462e3e8031b 100644 assert(_succ != current, "invariant"); assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); assert(current->thread_state() != _thread_blocked, "invariant"); -@@ -706,6 +715,7 @@ void ObjectMonitor::EnterI(JavaThread* current) { +@@ -752,6 +761,7 @@ void ObjectMonitor::EnterI(JavaThread* current) { } // The Spin failed -- Enqueue and park the thread ... @@ -74361,7 +75754,7 @@ index 2214713aa4b..462e3e8031b 100644 assert(owner_raw() != current, "invariant"); assert(_Responsible != current, "invariant"); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp -index 0eb4015a246..9aa9d7ef86f 100644 +index bdf93e1d3b4..ee796ccfe3e 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -22,6 +22,12 @@ @@ -74377,7 +75770,7 @@ index 0eb4015a246..9aa9d7ef86f 100644 #include "precompiled.hpp" #include "cds/cdsConfig.hpp" #include "classfile/javaClasses.hpp" -@@ -1308,7 +1314,8 @@ bool os::is_first_C_frame(frame* fr) { +@@ -1330,7 +1336,8 @@ bool os::is_first_C_frame(frame* fr) { if ((uintptr_t)fr->sender_sp() == (uintptr_t)-1 || is_pointer_bad(fr->sender_sp())) return true; uintptr_t old_fp = (uintptr_t)fr->link_or_null(); @@ -74428,8 +75821,69 @@ index fac76262f3c..f41cf843d31 100644 static double __kernel_sin(double x, double y, int iy) { +diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp +index 74286a4ac98..9523981fb27 100644 +--- a/src/hotspot/share/runtime/stubRoutines.cpp ++++ b/src/hotspot/share/runtime/stubRoutines.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "asm/codeBuffer.hpp" + #include "asm/macroAssembler.inline.hpp" +@@ -127,6 +133,8 @@ address StubRoutines::_electronicCodeBook_encryptAESCrypt = nullptr; + address StubRoutines::_electronicCodeBook_decryptAESCrypt = nullptr; + address StubRoutines::_counterMode_AESCrypt = nullptr; + address StubRoutines::_galoisCounterMode_AESCrypt = nullptr; ++address StubRoutines::_descrypt_encryptBlock = nullptr; ++address StubRoutines::_descrypt_decryptBlock = nullptr; + address StubRoutines::_ghash_processBlocks = nullptr; + address StubRoutines::_chacha20Block = nullptr; + address StubRoutines::_base64_encodeBlock = nullptr; +diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp +index 65b0c0d2f26..802ff640371 100644 +--- a/src/hotspot/share/runtime/stubRoutines.hpp ++++ b/src/hotspot/share/runtime/stubRoutines.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_RUNTIME_STUBROUTINES_HPP + #define SHARE_RUNTIME_STUBROUTINES_HPP + +@@ -211,6 +217,8 @@ class StubRoutines: AllStatic { + static address _counterMode_AESCrypt; + static address _galoisCounterMode_AESCrypt; + static address _ghash_processBlocks; ++ static address _descrypt_encryptBlock; ++ static address _descrypt_decryptBlock; + static address _chacha20Block; + static address _base64_encodeBlock; + static address _base64_decodeBlock; +@@ -415,6 +423,8 @@ class StubRoutines: AllStatic { + static address intpoly_assign() { return _intpoly_assign; } + static address counterMode_AESCrypt() { return _counterMode_AESCrypt; } + static address ghash_processBlocks() { return _ghash_processBlocks; } ++ static address descrypt_encryptBlock() { return _descrypt_encryptBlock; } ++ static address descrypt_decryptBlock() { return _descrypt_decryptBlock; } + static address chacha20Block() { return _chacha20Block; } + static address base64_encodeBlock() { return _base64_encodeBlock; } + static address base64_decodeBlock() { return _base64_decodeBlock; } diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp -index 34eafb01c6d..c663e01e221 100644 +index 047f6703b54..513a85ef6b2 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -22,6 +22,12 @@ @@ -74445,7 +75899,7 @@ index 34eafb01c6d..c663e01e221 100644 #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" #include "gc/shared/collectedHeap.hpp" -@@ -493,7 +499,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread +@@ -509,7 +515,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread } static bool useHeavyMonitors() { @@ -74455,7 +75909,7 @@ index 34eafb01c6d..c663e01e221 100644 #else return false; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp -index 54d591ff141..425daacb947 100644 +index ea12eaec6b0..c1a4a121ccc 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -22,6 +22,12 @@ @@ -74471,7 +75925,7 @@ index 54d591ff141..425daacb947 100644 #include "precompiled.hpp" #include "cds/filemap.hpp" #include "ci/ciField.hpp" -@@ -1512,6 +1518,7 @@ +@@ -1500,6 +1506,7 @@ declare_c2_type(StoreFenceNode, MemBarNode) \ declare_c2_type(MemBarVolatileNode, MemBarNode) \ declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ @@ -74480,7 +75934,7 @@ index 54d591ff141..425daacb947 100644 declare_c2_type(BlackholeNode, MultiNode) \ declare_c2_type(InitializeNode, MemBarNode) \ diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp -index bfbaaa58acc..74e56975081 100644 +index 244b18ecdd4..cdb392b5ef2 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp @@ -22,6 +22,12 @@ @@ -74515,6 +75969,122 @@ index bfbaaa58acc..74e56975081 100644 #if defined(PPC32) || defined(PPC64) #ifndef PPC #define PPC +diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESCrypt.java b/src/java.base/share/classes/com/sun/crypto/provider/DESCrypt.java +index acbde75cd84..9967a696b30 100644 +--- a/src/java.base/share/classes/com/sun/crypto/provider/DESCrypt.java ++++ b/src/java.base/share/classes/com/sun/crypto/provider/DESCrypt.java +@@ -23,10 +23,18 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + package com.sun.crypto.provider; + + import java.security.InvalidKeyException; + ++import jdk.internal.vm.annotation.IntrinsicCandidate; ++ + /** + * This is the internal DES class responsible for encryption and + * decryption of a byte array of size DES_BLOCK_SIZE. +@@ -558,7 +566,15 @@ void init(boolean decrypting, String algorithm, byte[] rawKey) + void encryptBlock(byte[] plain, int plainOffset, + byte[] cipher, int cipherOffset) + { +- cipherBlock(plain, plainOffset, cipher, cipherOffset); ++ implEncryptBlock(plain, plainOffset, cipher, cipherOffset); ++ } ++ ++ // Encryption operation. Possibly replaced with a compiler intrinsic. ++ @IntrinsicCandidate ++ void implEncryptBlock(byte[] in, int inOffset, ++ byte[] out, int outOffset) ++ { ++ cipherBlock(in, inOffset, out, outOffset); + } + + /** +@@ -581,11 +597,18 @@ void encryptBlock(byte[] plain, int plainOffset, + void decryptBlock(byte[] cipher, int cipherOffset, + byte[] plain, int plainOffset) + { +- cipherBlock(cipher, cipherOffset, plain, plainOffset); ++ implDecryptBlock(cipher, cipherOffset, plain, plainOffset); + } + ++ // Decrypt operation. Possibly replaced with a compiler intrinsic. ++ @IntrinsicCandidate ++ void implDecryptBlock(byte[] in, int inOffset, ++ byte[] out, int outOffset) ++ { ++ cipherBlock(in, inOffset, out, outOffset); ++ } + +- void cipherBlock(byte[] in, int inOffset, byte[] out, int outOffset) { ++ private void cipherBlock(byte[] in, int inOffset, byte[] out, int outOffset) { + byte key[]; + int temp; + int i, j; +diff --git a/src/java.base/share/classes/com/sun/crypto/provider/DESedeCrypt.java b/src/java.base/share/classes/com/sun/crypto/provider/DESedeCrypt.java +index 496a59b002a..94eb2828a2c 100644 +--- a/src/java.base/share/classes/com/sun/crypto/provider/DESedeCrypt.java ++++ b/src/java.base/share/classes/com/sun/crypto/provider/DESedeCrypt.java +@@ -23,6 +23,12 @@ + * questions. + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + package com.sun.crypto.provider; + + import java.security.InvalidKeyException; +@@ -116,15 +122,15 @@ void encryptBlock(byte[] plain, int plainOffset, + { + expandedKey = key1; + decrypting = false; +- cipherBlock(plain, plainOffset, buf1, 0); ++ implEncryptBlock(plain, plainOffset, buf1, 0); + + expandedKey = key2; + decrypting = true; +- cipherBlock(buf1, 0, buf2, 0); ++ implDecryptBlock(buf1, 0, buf2, 0); + + expandedKey = key3; + decrypting = false; +- cipherBlock(buf2, 0, cipher, cipherOffset); ++ implEncryptBlock(buf2, 0, cipher, cipherOffset); + } + + /** +@@ -146,15 +152,15 @@ void decryptBlock(byte[] cipher, int cipherOffset, + { + expandedKey = key3; + decrypting = true; +- cipherBlock(cipher, cipherOffset, buf1, 0); ++ implDecryptBlock(cipher, cipherOffset, buf1, 0); + + expandedKey = key2; + decrypting = false; +- cipherBlock(buf1, 0, buf2, 0); ++ implEncryptBlock(buf1, 0, buf2, 0); + + expandedKey = key1; + decrypting = true; +- cipherBlock(buf2, 0, plain, plainOffset); ++ implDecryptBlock(buf2, 0, plain, plainOffset); + } + + private boolean keyEquals(byte[] key1, int off1, diff --git a/src/java.base/share/classes/jdk/internal/foreign/CABI.java b/src/java.base/share/classes/jdk/internal/foreign/CABI.java index 500e312b2f3..7fe68049d17 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/CABI.java @@ -74554,7 +76124,7 @@ index 500e312b2f3..7fe68049d17 100644 return FALLBACK; // fallback linker } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java -index d90e5acd259..10c77f1de73 100644 +index 4f3baaa0e71..c803a2c9c84 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -22,6 +22,12 @@ @@ -74587,7 +76157,7 @@ index d90e5acd259..10c77f1de73 100644 public interface UpcallStubFactory { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java -index 5f625242182..df1b9a65a53 100644 +index 83698398eda..a8e88da3676 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -22,6 +22,12 @@ @@ -74611,7 +76181,7 @@ index 5f625242182..df1b9a65a53 100644 import jdk.internal.foreign.abi.ppc64.aix.AixPPC64Linker; import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64Linker; import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker; -@@ -250,6 +257,7 @@ public static Linker getSystemLinker() { +@@ -251,6 +258,7 @@ public static Linker getSystemLinker() { case LINUX_PPC_64_LE -> LinuxPPC64leLinker.getInstance(); case LINUX_RISCV_64 -> LinuxRISCV64Linker.getInstance(); case LINUX_S390 -> LinuxS390Linker.getInstance(); @@ -75291,13 +76861,13 @@ index 00000000000..ab68e36a0c1 +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64Linker.java new file mode 100644 -index 00000000000..1669486e747 +index 00000000000..c6a48cb04c0 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64Linker.java -@@ -0,0 +1,77 @@ +@@ -0,0 +1,72 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -75363,11 +76933,6 @@ index 00000000000..1669486e747 + } + + @Override -+ protected ByteOrder linkerByteOrder() { -+ return ByteOrder.LITTLE_ENDIAN; -+ } -+ -+ @Override + public Map canonicalLayouts() { + return CANONICAL_LAYOUTS; + } @@ -78619,7 +80184,7 @@ index 14f97412b3d..23862a52f22 100644 jdk.vm.ci.hotspot.riscv64.RISCV64HotSpotJVMCIBackendFactory; } diff --git a/src/utils/hsdis/binutils/hsdis-binutils.c b/src/utils/hsdis/binutils/hsdis-binutils.c -index d011dc579b5..7747fc06e05 100644 +index fda6a53a6d3..00ae1088782 100644 --- a/src/utils/hsdis/binutils/hsdis-binutils.c +++ b/src/utils/hsdis/binutils/hsdis-binutils.c @@ -44,6 +44,12 @@ @@ -78635,7 +80200,7 @@ index d011dc579b5..7747fc06e05 100644 /* hsdis.c -- dump a range of addresses as native instructions This implements the plugin protocol required by the HotSpot PrintAssembly option. -@@ -502,6 +508,9 @@ static const char* native_arch_name() { +@@ -498,6 +504,9 @@ static const char* native_arch_name() { #endif #ifdef LIBARCH_riscv64 res = "riscv:rv64"; @@ -78645,6 +80210,96 @@ index d011dc579b5..7747fc06e05 100644 #endif if (res == NULL) res = "architecture not set in Makefile!"; +diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt +index 2364d601cd7..d2cf6665aca 100644 +--- a/test/hotspot/jtreg/ProblemList-Xcomp.txt ++++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt +@@ -21,6 +21,12 @@ + # questions. + # + ++# ++# This file has been modified by Loongson Technology in 2023. These ++# modifications are Copyright (c) 2022, 2023, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# ++ + ############################################################################# + # + # List of quarantined tests for testing in Xcomp mode. +@@ -52,3 +58,19 @@ vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 829 + vmTestbase/nsk/stress/thread/thread006.java 8321476 linux-all + + gc/arguments/TestNewSizeFlags.java 8299116 macosx-aarch64 ++ ++# loongson added ++gc/shenandoah/TestAllocHumongousFragment.java#aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestAllocHumongousFragment.java#iu-aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestAllocIntArrays.java#aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestAllocIntArrays.java#iu-aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestAllocObjectArrays.java#aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestAllocObjectArrays.java#iu-aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestSieveObjects.java#aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestSieveObjects.java#iu-aggressive #27323 generic-loongarch64 ++gc/shenandoah/TestStringDedupStress.java#default #27323 generic-loongarch64 ++gc/shenandoah/TestStringDedupStress.java#iu #27323 generic-loongarch64 ++gc/stress/gcold/TestGCOldWithShenandoah.java#aggressive #27323 generic-loongarch64 ++gc/stress/gcold/TestGCOldWithShenandoah.java#iu-aggressive #27323 generic-loongarch64 ++gc/TestAllocHumongousFragment.java#aggressive #30977 generic-loongarch64 ++gc/TestAllocHumongousFragment.java#iu-aggressive #30977 generic-loongarch64 +diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt +index d7d600aad49..ce0b7ddc15a 100644 +--- a/test/hotspot/jtreg/ProblemList-zgc.txt ++++ b/test/hotspot/jtreg/ProblemList-zgc.txt +@@ -21,6 +21,12 @@ + # questions. + # + ++# ++# This file has been modified by Loongson Technology in 2023. These ++# modifications are Copyright (c) 2022, 2023, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# ++ + ############################################################################# + # + # List of quarantined tests for testing with ZGC. +@@ -48,3 +54,6 @@ serviceability/sa/TestHeapDumpForInvokeDynamic.java 8315646 generic- + vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64 + + vmTestbase/nsk/sysdict/vm/stress/chain/chain007/chain007.java 8298991 linux-x64 ++ ++# loongson added ++compiler/vectorapi/TestVectorShiftImm.java generic-loongarch64 +diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt +index 3350a8ef9ec..9fe1a7b49a4 100644 +--- a/test/hotspot/jtreg/ProblemList.txt ++++ b/test/hotspot/jtreg/ProblemList.txt +@@ -21,6 +21,12 @@ + # questions. + # + ++# ++# This file has been modified by Loongson Technology in 2024. These ++# modifications are Copyright (c) 2019, 2024, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# ++ + ############################################################################# + # + # List of quarantined tests -- tests that should not be run by default, because +@@ -190,3 +196,11 @@ vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEa + vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64 + + vmTestbase/nsk/monitoring/ThreadMXBean/findMonitorDeadlockedThreads/find006/TestDescription.java 8310144 macosx-aarch64 ++ ++# loongson added ++compiler/loopopts/TestUnreachableInnerLoop.java #27128 generic-loongarch64 ++runtime/cds/appcds/dynamicArchive/TestAutoCreateSharedArchiveUpgrade.java #30772 generic-all ++runtime/cds/appcds/jigsaw/module/ModuleOption.java #33051 generic-all ++serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java #30722 generic-loongarch64 ++vmTestbase/gc/gctests/SoftReference/soft004/soft004.java #28134 generic-loongarch64 ++vmTestbase/gc/gctests/WeakReference/weak004/weak004.java #28134 generic-loongarch64 diff --git a/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java b/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java index 465999eac7f..ba9629d5e77 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java @@ -78832,7 +80487,7 @@ index 5968b7221c7..6bcdf4d189d 100644 * @library /test/lib / * @run driver compiler.c2.irTests.TestVectorizationNotRun diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java -index 67c26ecbddf..ba69c910ce6 100644 +index 899be4bbc9c..3aefead5d13 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeTypeConversion.java @@ -21,6 +21,12 @@ @@ -78858,7 +80513,7 @@ index 67c26ecbddf..ba69c910ce6 100644 * @run driver compiler.c2.irTests.TestVectorizeTypeConversion */ diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java -index ebe3fe63ccf..04ea3cccdef 100644 +index f477a08f717..d2405854063 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestVectorizeURShiftSubword.java @@ -22,6 +22,12 @@ @@ -78874,17 +80529,17 @@ index ebe3fe63ccf..04ea3cccdef 100644 package compiler.c2.irTests; import compiler.lib.ir_framework.*; -@@ -34,7 +40,7 @@ - * @bug 8283307 +@@ -35,7 +41,7 @@ * @key randomness * @summary Auto-vectorization enhancement for unsigned shift right on signed subword types -- * @requires ((os.arch=="amd64" | os.arch=="x86_64") & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) | os.arch=="aarch64" -+ * @requires ((os.arch=="amd64" | os.arch=="x86_64") & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) | os.arch=="aarch64" | os.arch=="loongarch64" + * @requires ((os.arch=="amd64" | os.arch=="x86_64") & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) | os.arch=="aarch64" | +- * (os.arch == "riscv64" & vm.cpu.features ~= ".*v,.*") ++ * (os.arch == "riscv64" & vm.cpu.features ~= ".*v,.*") | os.arch=="loongarch64" * @library /test/lib / * @run driver compiler.c2.irTests.TestVectorizeURShiftSubword */ diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java -index 4c56daebfb8..92836130408 100644 +index ac3a6d9a8c6..c17598902ff 100644 --- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java +++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java @@ -21,12 +21,18 @@ @@ -78908,7 +80563,7 @@ index 4c56daebfb8..92836130408 100644 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/timeout=600 -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java -index 03016ea3dd6..62ce6c1a7a5 100644 +index fdc8f63f9e0..993cf68d011 100644 --- a/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java +++ b/test/hotspot/jtreg/compiler/cpuflags/TestAESIntrinsicsOnUnsupportedConfig.java @@ -21,6 +21,12 @@ @@ -78933,33 +80588,6 @@ index 03016ea3dd6..62ce6c1a7a5 100644 * @requires vm.compiler1.enabled | !vm.graal.enabled * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestBitShuffleOpers.java b/test/hotspot/jtreg/compiler/intrinsics/TestBitShuffleOpers.java -index 9a7e0c6b9f2..847ed1e7b51 100644 ---- a/test/hotspot/jtreg/compiler/intrinsics/TestBitShuffleOpers.java -+++ b/test/hotspot/jtreg/compiler/intrinsics/TestBitShuffleOpers.java -@@ -21,6 +21,12 @@ - * questions. - */ - -+/* -+ * This file has been modified by Loongson Technology in 2023, These -+ * modifications are Copyright (c) 2023, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - /** - * @test - * @bug 8283894 -@@ -31,7 +37,8 @@ - * (vm.cpu.features ~= ".*bmi2.*" & vm.cpu.features ~= ".*bmi1.*" & - * vm.cpu.features ~= ".*sse2.*")) | - * (os.arch=="aarch64" & vm.cpu.features ~= ".*svebitperm.*") | -- * (os.arch=="riscv64" & vm.cpu.features ~= ".*v,.*")) -+ * (os.arch=="riscv64" & vm.cpu.features ~= ".*v,.*") | -+ * (os.arch=="loongarch64")) - * @library /test/lib / - * @run driver compiler.intrinsics.TestBitShuffleOpers - */ diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java index 99a594ade69..61fa03381c5 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java @@ -79163,10 +80791,10 @@ index 55f8375332d..ff5d931ec51 100644 // the ChaCha20 known answer tests in // com/sun/crypto/provider/Cipher are sufficient. diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java -index 0541121c127..d9fe8c91dc4 100644 +index cd0f0b636a7..59313f41b85 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java -@@ -21,11 +21,17 @@ +@@ -21,12 +21,18 @@ * questions. */ @@ -79180,16 +80808,17 @@ index 0541121c127..d9fe8c91dc4 100644 * @test * @bug 8289551 8302976 * @summary Verify conversion between float and the binary16 format -- * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" -+ * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" | os.arch=="loongarch64" + * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" +- * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") ++ * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") | os.arch=="loongarch64" * @requires vm.compiler1.enabled & vm.compiler2.enabled * @requires vm.compMode != "Xcomp" * @comment default run diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN.java b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN.java -index 38060dfb504..151caa94346 100644 +index 8aa83544f9f..c28b9a1d130 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16ConversionNaN.java -@@ -21,11 +21,17 @@ +@@ -21,12 +21,18 @@ * questions. */ @@ -79203,16 +80832,17 @@ index 38060dfb504..151caa94346 100644 * @test * @bug 8289551 8302976 * @summary Verify NaN sign and significand bits are preserved across conversions -- * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" -+ * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" | os.arch=="loongarch64" + * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" +- * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") ++ * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") | os.arch=="loongarch64" * @requires vm.compiler1.enabled & vm.compiler2.enabled * @requires vm.compMode != "Xcomp" * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java b/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java -index 492901f0046..e95554fa944 100644 +index acf5b3c4aea..64f657069c7 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java -@@ -21,11 +21,17 @@ +@@ -21,12 +21,18 @@ * questions. */ @@ -79226,16 +80856,17 @@ index 492901f0046..e95554fa944 100644 * @test * @bug 8302976 * @summary Verify conversion between float and the binary16 format -- * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch == "aarch64" -+ * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch == "aarch64" | os.arch == "loongarch64" + * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch == "aarch64" +- * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") ++ * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") | os.arch == "loongarch64" * @requires vm.compiler1.enabled & vm.compiler2.enabled * @requires vm.compMode != "Xcomp" * @comment default run: diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java b/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java -index b4ba578c9f2..27e6b86abe2 100644 +index af89d353ab2..a1d2d8d04ce 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java -@@ -21,11 +21,17 @@ +@@ -21,12 +21,18 @@ * questions. */ @@ -79249,8 +80880,9 @@ index b4ba578c9f2..27e6b86abe2 100644 * @test * @bug 8302976 * @summary Verify conversion cons between float and the binary16 format -- * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" -+ * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" | os.arch == "loongarch64" + * @requires (vm.cpu.features ~= ".*avx512vl.*" | vm.cpu.features ~= ".*f16c.*") | os.arch=="aarch64" +- * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") ++ * | (os.arch == "riscv64" & vm.cpu.features ~= ".*zfh.*") | os.arch == "loongarch64" * @requires vm.compiler1.enabled & vm.compiler2.enabled * @requires vm.compMode != "Xcomp" * @comment default run: @@ -79354,7 +80986,7 @@ index 26bc03c271b..606f0d4f17d 100644 * different string length. This test creates string with specified * size and longer string, which is same at beginning. diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java -index 7483c45a654..68c280f1f39 100644 +index 97583b45458..587b702d891 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java @@ -20,10 +20,18 @@ @@ -79384,7 +81016,7 @@ index 7483c45a654..68c280f1f39 100644 import jdk.vm.ci.code.test.riscv64.RISCV64TestAssembler; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompiledCode; -@@ -80,6 +89,8 @@ private TestAssembler createAssembler() { +@@ -81,6 +90,8 @@ private TestAssembler createAssembler() { return new AArch64TestAssembler(codeCache, config); } else if (arch instanceof RISCV64) { return new RISCV64TestAssembler(codeCache, config); @@ -79530,7 +81162,7 @@ index ebd57b6faaf..ed15dff3a5e 100644 */ package jdk.vm.ci.code.test; diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java -index 80c63392b6e..f667c799773 100644 +index 82058ec02cf..bf7175d1cb9 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java @@ -21,10 +21,16 @@ @@ -79548,7 +81180,7 @@ index 80c63392b6e..f667c799773 100644 * @requires vm.jvmci - * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" + * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" | vm.simpleArch == "loongarch64" - * @library / + * @library /test/lib / * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot * jdk.internal.vm.ci/jdk.vm.ci.meta @@ -32,9 +38,10 @@ @@ -79633,13 +81265,13 @@ index 543128e932c..4aa99f24060 100644 diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java new file mode 100644 -index 00000000000..4c76868453a +index 00000000000..d8d701a8c81 --- /dev/null +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/loongarch64/LoongArch64TestAssembler.java -@@ -0,0 +1,568 @@ +@@ -0,0 +1,616 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. 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 @@ -79686,6 +81318,7 @@ index 00000000000..4c76868453a +public class LoongArch64TestAssembler extends TestAssembler { + + private static final Register scratchRegister = LoongArch64.SCR1; ++ private static final Register scratchRegister2 = LoongArch64.SCR2; + private static final Register doubleScratch = LoongArch64.f23; + private static final RegisterArray nativeGeneralParameterRegisters = new RegisterArray(LoongArch64.a0, + LoongArch64.a1, LoongArch64.a2, @@ -79699,6 +81332,22 @@ index 00000000000..4c76868453a + LoongArch64.f7); + private static int currentGeneral = 0; + private static int currentFloat = 0; ++ ++ public enum ConditionFlag { ++ EQ(0b010110), ++ NE(0b010111), ++ LT(0b011000), ++ GE(0b011001), ++ LTU(0b011010), ++ GEU(0b011011); ++ ++ public final int encoding; ++ ++ ConditionFlag(int encoding) { ++ this.encoding = encoding; ++ } ++ } ++ + public LoongArch64TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config) { + super(codeCache, config, + 16 /* initialFrameSize */, 16 /* stackAlignment */, @@ -79721,6 +81370,13 @@ index 00000000000..4c76868453a + code.emitInt(0x3400000); + } + ++ private void emitPcaddi(Register rd, int si20) { ++ // pcaddi ++ code.emitInt((0b0001100 << 25) ++ | ((low(si20, 20) >> 2) << 5) ++ | rd.encoding); ++ } ++ + private void emitPcaddu12i(Register rj, int si20) { + // pcaddu12i + code.emitInt((0b0001110 << 25) @@ -79881,6 +81537,16 @@ index 00000000000..4c76868453a + | rd.encoding); + } + ++ protected void emitBranch(Register rj, Register rd, ConditionFlag condition, int offs) { ++ // B.cond ++ check(isSignedNbit(18, offs) && (offs & 0b11) == 0, ++ "0x%x must be a 18-bit signed number and 4-byte aligned", offs); ++ code.emitInt((condition.encoding << 26) ++ | (low16(offs >> 2) << 10) ++ | (rj.encoding << 5) ++ | rd.encoding); ++ } ++ + @Override + public void emitGrowStack(int size) { + assert size % 16 == 0; @@ -79907,9 +81573,21 @@ index 00000000000..4c76868453a + emitStoreRegister(LoongArch64.fp, LoongArch64Kind.QWORD, LoongArch64.sp, 16); + emitGrowStack(-16); + emitMove(LoongArch64.fp, LoongArch64.sp); ++ emitNMethodEntryBarrier(); + setDeoptRescueSlot(newStackSlot(LoongArch64Kind.QWORD)); + } + ++ private void emitNMethodEntryBarrier() { ++ recordMark(config.MARKID_ENTRY_BARRIER_PATCH); ++ DataSectionReference ref = emitDataItem(0); ++ emitLoadPointer(scratchRegister, LoongArch64Kind.UDWORD, ref); ++ code.emitInt(0x38720014); // dbar 0x14 loadload|loadstore ++ Register thread = LoongArch64.s6; ++ emitLoadPointer(scratchRegister2, LoongArch64Kind.UDWORD, thread, config.threadDisarmedOffset); ++ emitBranch(scratchRegister, scratchRegister2, ConditionFlag.EQ, 4*4); // jump over slow path, runtime call ++ emitCall(config.nmethodEntryBarrier); ++ } ++ + @Override + public void emitEpilogue() { + recordMark(config.MARKID_DEOPT_HANDLER_ENTRY); @@ -80004,8 +81682,11 @@ index 00000000000..4c76868453a + + @Override + public Register emitLoadPointer(Register b, int offset) { -+ Register ret = newRegister(); -+ emitLoadRegister(ret, LoongArch64Kind.QWORD, b, offset); ++ return emitLoadPointer(newRegister(), LoongArch64Kind.QWORD, b, offset); ++ } ++ ++ public Register emitLoadPointer(Register ret, LoongArch64Kind kind, Register b, int offset) { ++ emitLoadRegister(ret, kind, b, offset); + return ret; + } + @@ -80014,20 +81695,21 @@ index 00000000000..4c76868453a + recordDataPatchInCode(ref); + + Register ret = newRegister(); -+ emitPcaddu12i(ret, 0xdead >> 12); -+ emitAdd(ret, ret, 0xdead & 0xfff); ++ emitPcaddi(ret, 0xdead); + emitLoadRegister(ret, LoongArch64Kind.UDWORD, ret, 0); + return ret; + } + + @Override + public Register emitLoadPointer(DataSectionReference ref) { ++ return emitLoadPointer(newRegister(), LoongArch64Kind.QWORD, ref); ++ } ++ ++ public Register emitLoadPointer(Register ret, LoongArch64Kind kind, DataSectionReference ref) { + recordDataPatchInCode(ref); + -+ Register ret = newRegister(); -+ emitPcaddu12i(ret, 0xdead >> 12); -+ emitAdd(ret, ret, 0xdead & 0xfff); -+ emitLoadRegister(ret, LoongArch64Kind.QWORD, ret, 0); ++ emitPcaddi(ret, 0xdead); ++ emitLoadRegister(ret, kind, ret, 0); + return ret; + } + @@ -80037,8 +81719,7 @@ index 00000000000..4c76868453a + data.emitDouble(c); + + recordDataPatchInCode(ref); -+ emitPcaddu12i(scratchRegister, 0xdead >> 12); -+ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); ++ emitPcaddi(scratchRegister, 0xdead); + emitLoadRegister(reg, LoongArch64Kind.DOUBLE, scratchRegister, 0); + return reg; + } @@ -80049,8 +81730,7 @@ index 00000000000..4c76868453a + data.emitFloat(c); + + recordDataPatchInCode(ref); -+ emitPcaddu12i(scratchRegister, 0xdead >> 12); -+ emitAdd(scratchRegister, scratchRegister, 0xdead & 0xfff); ++ emitPcaddi(scratchRegister, 0xdead); + emitLoadRegister(reg, LoongArch64Kind.SINGLE, scratchRegister, 0); + return reg; + } @@ -80206,7 +81886,7 @@ index 00000000000..4c76868453a + +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java -index 9e91268edff..2b25abb24c5 100644 +index 1fb68439afb..e8723ee838c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -21,6 +21,12 @@ @@ -80222,7 +81902,7 @@ index 9e91268edff..2b25abb24c5 100644 package compiler.lib.ir_framework; import compiler.lib.ir_framework.driver.irmatching.mapping.*; -@@ -375,13 +381,13 @@ +@@ -380,13 +386,13 @@ public static final String CHECKCAST_ARRAY = PREFIX + "CHECKCAST_ARRAY" + POSTFIX; static { @@ -80288,7 +81968,7 @@ index b9a3028978f..36efb0b63ba 100644 * @run main/othervm compiler.rangechecks.TestRangeCheckHoistingScaledIV */ diff --git a/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java -index df221959bb5..a15ac48e3fa 100644 +index 3daf12df879..31018941a9c 100644 --- a/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java +++ b/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java @@ -21,6 +21,12 @@ @@ -80367,7 +82047,7 @@ index 5dd938442cc..2ec4cab8f62 100644 * @run driver compiler.sharedstubs.SharedStubToInterpTest -XX:-TieredCompilation * diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java -index 689c7c8cc2f..f734c1baa3f 100644 +index 27fe9989247..a073e703dbe 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -21,6 +21,12 @@ @@ -80383,20 +82063,21 @@ index 689c7c8cc2f..f734c1baa3f 100644 package compiler.testlibrary.sha.predicate; import jdk.test.lib.Platform; -@@ -61,19 +67,22 @@ - +@@ -62,20 +68,23 @@ public static final BooleanSupplier MD5_INSTRUCTION_AVAILABLE = new OrPredicate(new CPUSpecificPredicate("aarch64.*", null, null), + new OrPredicate(new CPUSpecificPredicate("riscv64.*", null, null), + new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), // x86 variants new OrPredicate(new CPUSpecificPredicate("amd64.*", null, null), new OrPredicate(new CPUSpecificPredicate("i386.*", null, null), -- new CPUSpecificPredicate("x86.*", null, null)))); -+ new CPUSpecificPredicate("x86.*", null, null))))); +- new CPUSpecificPredicate("x86.*", null, null))))); ++ new CPUSpecificPredicate("x86.*", null, null)))))); public static final BooleanSupplier SHA1_INSTRUCTION_AVAILABLE = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha1" }, null), - new OrPredicate(new CPUSpecificPredicate("riscv64.*", new String[] { "sha1" }, null), + // SHA-1 intrinsic is implemented with scalar instructions on riscv64 + new OrPredicate(new CPUSpecificPredicate("riscv64.*", null, null), new OrPredicate(new CPUSpecificPredicate("s390.*", new String[] { "sha1" }, null), + // Basic instructions are used to implement SHA1 Intrinsics on LA, so "sha1" feature is not needed. + new OrPredicate(new CPUSpecificPredicate("loongarch64.*", null, null), @@ -80408,7 +82089,7 @@ index 689c7c8cc2f..f734c1baa3f 100644 public static final BooleanSupplier SHA256_INSTRUCTION_AVAILABLE = new OrPredicate(new CPUSpecificPredicate("aarch64.*", new String[] { "sha256" }, null), -@@ -81,12 +90,14 @@ +@@ -83,12 +92,14 @@ new OrPredicate(new CPUSpecificPredicate("s390.*", new String[] { "sha256" }, null), new OrPredicate(new CPUSpecificPredicate("ppc64.*", new String[] { "sha" }, null), new OrPredicate(new CPUSpecificPredicate("ppc64le.*", new String[] { "sha" }, null), @@ -80478,7 +82159,7 @@ index 426dec67019..ea25a81a354 100644 * * @run driver compiler.vectorapi.VectorLogicalOpIdentityTest diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java -index 154567922bd..d81a90f2fcb 100644 +index bfb95c0651c..7dcc85f6c32 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java @@ -21,6 +21,12 @@ @@ -80494,12 +82175,12 @@ index 154567922bd..d81a90f2fcb 100644 package compiler.vectorapi; import compiler.lib.ir_framework.*; -@@ -42,7 +48,7 @@ - * @library /test/lib / +@@ -43,7 +49,7 @@ * @summary [vectorapi] REVERSE_BYTES for byte type should not emit any instructions * @requires vm.compiler2.enabled -- * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" -+ * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" | os.arch == "loongarch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" | +- * (os.arch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") ++ * (os.arch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") | os.arch == "loongarch64" * @modules jdk.incubator.vector * * @run driver compiler.vectorapi.VectorReverseBytesTest @@ -80561,7 +82242,7 @@ index 00000000000..3298628333e + + diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java -index 032ed40de98..015239e0dd3 100644 +index 6cdd3754c09..581e03b31c0 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java +++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java @@ -21,6 +21,12 @@ @@ -80577,7 +82258,7 @@ index 032ed40de98..015239e0dd3 100644 package compiler.vectorapi.reshape.utils; import java.util.List; -@@ -336,4 +342,62 @@ +@@ -805,4 +811,62 @@ makePair(SSPEC128, ISPEC128, true), makePair(ISPEC64, LSPEC128, true) ); @@ -80666,37 +82347,11 @@ index e3baed37804..18b9333b1d1 100644 * @run driver compiler.c2.irTests.TestAutoVecIntMinMax */ -diff --git a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java -index 889cc68f876..a9e769ef99c 100644 ---- a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java -+++ b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java -@@ -21,6 +21,12 @@ - * questions. - */ - -+/* -+ * This file has been modified by Loongson Technology in 2023, These -+ * modifications are Copyright (c) 2023, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - /** - * @test - * @bug 8257531 -@@ -29,7 +35,7 @@ - * - * @requires vm.flagless - * @requires vm.compiler2.enabled & vm.debug == true -- * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" -+ * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="loongarch64" - * - * @run driver compiler.vectorization.TestBufferVectorization array - * @run driver compiler.vectorization.TestBufferVectorization arrayOffset diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java -index 49035332fa4..8a1f3aa6882 100644 +index 96324c62c32..4a020b98d7b 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java -@@ -21,12 +21,18 @@ +@@ -21,6 +21,12 @@ * questions. */ @@ -80709,39 +82364,16 @@ index 49035332fa4..8a1f3aa6882 100644 /** * @test * @bug 8294588 - * @summary Auto-vectorize Float.floatToFloat16, Float.float16ToFloat APIs +@@ -28,7 +34,8 @@ * @requires vm.compiler2.enabled -- * @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx512f.*" | vm.cpu.features ~= ".*f16c.*")) | os.arch == "aarch64" -+ * @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx512f.*" | vm.cpu.features ~= ".*f16c.*")) | os.arch == "aarch64" | os.arch == "loongarch64" + * @requires (os.simpleArch == "x64" & (vm.cpu.features ~= ".*avx512f.*" | vm.cpu.features ~= ".*f16c.*")) | + * os.arch == "aarch64" | +- * (os.arch == "riscv64" & vm.cpu.features ~= ".*zvfh.*") ++ * (os.arch == "riscv64" & vm.cpu.features ~= ".*zvfh.*") | ++ * os.arch == "loongarch64" * @library /test/lib / * @run driver compiler.vectorization.TestFloatConversionsVector */ -diff --git a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java -index abbabca0f2a..b7bde7068b5 100644 ---- a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java -+++ b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java -@@ -21,13 +21,20 @@ - * questions. - */ - -+/* -+ * This file has been modified by Loongson Technology in 2023, These -+ * modifications are Copyright (c) 2023, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - /** - * @test - * @key randomness - * @summary Test vectorization of numberOfTrailingZeros/numberOfLeadingZeros for Long - * @requires vm.compiler2.enabled - * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | --* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") -+* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") | -+* (os.simpleArch == "loongarch64") - * @library /test/lib / - * @run driver compiler.vectorization.TestNumberOfContinuousZeros - */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopulateIndex.java b/test/hotspot/jtreg/compiler/vectorization/TestPopulateIndex.java index e23accd27b0..e5b7682a7d1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopulateIndex.java @@ -80768,36 +82400,11 @@ index e23accd27b0..e5b7682a7d1 100644 * @library /test/lib / * @run driver compiler.vectorization.TestPopulateIndex */ -diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java -index 1144186d8e5..f36bb209a6b 100644 ---- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java -+++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java -@@ -20,12 +20,19 @@ - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -+ -+/* -+ * This file has been modified by Loongson Technology in 2023, These -+ * modifications are Copyright (c) 2023, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - /** - * @test - * @bug 8290034 - * @summary Auto-vectorization of Reverse bit operation. - * @requires vm.compiler2.enabled -- * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" -+ * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.arch == "aarch64" | os.arch=="loongarch64" - * @library /test/lib / - * @run driver compiler.vectorization.TestReverseBitsVector - */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java -index 47813e2790e..d30f2d3d177 100644 +index 71c9114121c..b99a235d1b3 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java -@@ -20,12 +20,19 @@ +@@ -20,13 +20,20 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ @@ -80813,8 +82420,9 @@ index 47813e2790e..d30f2d3d177 100644 * @bug 8288112 * @summary Auto-vectorization of ReverseBytes operations. * @requires vm.compiler2.enabled -- * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" -+ * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" | os.simpleArch == "loongarch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" | +- * (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") ++ * (os.simpleArch == "riscv64" & vm.cpu.features ~= ".*zvbb.*") | os.simpleArch == "loongarch64" * @library /test/lib / * @run driver compiler.vectorization.TestReverseBytes */ @@ -80845,10 +82453,10 @@ index 66943d68a67..aee6ecfa703 100644 * @run driver compiler.vectorization.TestSignumVector */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java -index a4eca0fe8dd..de44f60520a 100644 +index 5c9fc7d4f5c..ea6ccc8dffb 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java -@@ -21,6 +21,12 @@ +@@ -22,6 +22,12 @@ * questions. */ @@ -80861,7 +82469,7 @@ index a4eca0fe8dd..de44f60520a 100644 /* * @test * @summary Vectorization test on array index fill -@@ -35,7 +41,7 @@ +@@ -36,7 +42,7 @@ * -XX:+WhiteBoxAPI * compiler.vectorization.runner.ArrayIndexFillTest * @@ -80897,10 +82505,10 @@ index 2e7302bba05..964c03955d1 100644 */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java -index 74262142247..920f0418e10 100644 +index c4f601f42c8..b456d067672 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java -@@ -21,6 +21,12 @@ +@@ -22,6 +22,12 @@ * questions. */ @@ -80912,18 +82520,18 @@ index 74262142247..920f0418e10 100644 + /* * @test - * @summary Vectorization test on bug-prone shift operation -@@ -35,7 +41,7 @@ + * @bug 8183390 8332905 +@@ -37,7 +43,7 @@ * -XX:+WhiteBoxAPI * compiler.vectorization.runner.ArrayShiftOpTest * -- * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") -+ * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") +- * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") ++ * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") | (os.simpleArch == "loongarch64") * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java -index a3fcdbaa9b0..3edbd0dd0ec 100644 +index c1bef52a8b1..c3bd084e307 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java @@ -22,6 +22,12 @@ @@ -80975,7 +82583,7 @@ index e2bf0492d2a..47a7a2b4e13 100644 */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java -index 80ebd7b64d0..22b92e861c5 100644 +index c6ecac096f9..e18d795cc54 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java @@ -22,6 +22,12 @@ @@ -80995,13 +82603,13 @@ index 80ebd7b64d0..22b92e861c5 100644 * -XX:+WhiteBoxAPI * compiler.vectorization.runner.BasicLongOpTest * -- * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") -+ * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") +- * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") ++ * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "riscv64") | (os.simpleArch == "loongarch64") * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java -index e06bbb05098..cc03fc31c99 100644 +index 8df1e03e3f4..2a363575484 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java @@ -22,6 +22,12 @@ @@ -81053,7 +82661,7 @@ index f1c8fea059b..9cf2023fa7d 100644 * */ diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java -index 8004d34f5ce..1001f48afe6 100644 +index f799c0bac21..b89519d4388 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -21,13 +21,19 @@ @@ -81077,12 +82685,137 @@ index 8004d34f5ce..1001f48afe6 100644 * @requires vm.gc.Shenandoah * * @run main/othervm --enable-native-access=ALL-UNNAMED -XX:+UnlockDiagnosticVMOptions +diff --git a/test/hotspot/jtreg/loongson/11541/VarHandleOpaque.java b/test/hotspot/jtreg/loongson/11541/VarHandleOpaque.java +new file mode 100644 +index 00000000000..e7349491f96 +--- /dev/null ++++ b/test/hotspot/jtreg/loongson/11541/VarHandleOpaque.java +@@ -0,0 +1,119 @@ ++/* ++ * Copyright (c) 2015, 2023, Loongson Technology. 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. ++ * ++ */ ++ ++/** ++ * @test id=default ++ * @summary Test whether the loading of VarHandle::getOpaque is reordered. ++ * @requires vm.flagless ++ * @run main/othervm/timeout=72000 VarHandleOpaque 100_000_000_000 ++ */ ++ ++/** ++ * @test id=server ++ * @summary Test whether the loading of VarHandle::getOpaque is reordered. ++ * @requires vm.flagless ++ * @run main/othervm/timeout=72000 -XX:-TieredCompilation -server VarHandleOpaque 100_000_000_000 ++ */ ++ ++/** ++ * @test id=Xint ++ * @summary Test whether the loading of VarHandle::getOpaque is reordered. ++ * @requires vm.flagless ++ * @run main/othervm/timeout=72000 -Xint VarHandleOpaque 32_000_000 ++ */ ++ ++ /** ++ * @test id=TieredStopAtLevel3 ++ * @summary Test whether the loading of VarHandle::getOpaque is reordered. ++ * @requires vm.flagless ++ * @run main/othervm/timeout=72000 -XX:TieredStopAtLevel=3 VarHandleOpaque 32_000_000 ++ */ ++ ++import java.lang.invoke.MethodHandles; ++import java.lang.invoke.VarHandle; ++ ++public class VarHandleOpaque { ++ static final VarHandleOpaque inst; ++ static final VarHandle VH; ++ static long upperBound; ++ long x; ++ ++ static { ++ try { ++ inst = new VarHandleOpaque(); ++ VH = MethodHandles.lookup().findVarHandle(VarHandleOpaque.class, "x", long.class); ++ } catch (NoSuchFieldException | IllegalAccessException e) { ++ throw new IllegalStateException(e); ++ } ++ } ++ ++ static public class Writer extends Thread { ++ public void run() { ++ for (long i = 0; i < upperBound; i++) { ++ VH.setOpaque(inst, i); ++ } ++ } ++ } ++ ++ static public class Reader extends Thread { ++ public void run() { ++ long former = (long)VH.getOpaque(inst); ++ long latter = 0; ++ while (latter < upperBound - 1) { ++ latter = (long)VH.getOpaque(inst); ++ if (former > latter) { ++ System.out.println(String.format("former(%d) > latter(%d)!", former, latter)); ++ System.exit(-1); ++ } ++ former = latter; ++ } ++ } ++ } ++ ++ public static void main(String[] args) { ++ upperBound = Long.parseLong(args[0].replaceAll("_", "")); ++ int processorsNum = Runtime.getRuntime().availableProcessors(); ++ int readerThreadsNum = 4 * processorsNum; ++ ++ Writer writer = new Writer(); ++ Reader[] readers = new Reader[readerThreadsNum]; ++ ++ writer.start(); ++ for (int i = 0; i < readerThreadsNum; i++) { ++ readers[i] = new Reader(); ++ readers[i].start(); ++ } ++ ++ try { ++ writer.join(); ++ } catch (Exception e) { ++ } ++ for (int i = 0; i < readerThreadsNum; i++) { ++ try { ++ readers[i].join(); ++ } catch (Exception e) { ++ } ++ } ++ } ++} diff --git a/test/hotspot/jtreg/loongson/25064/NUMAHelper.java b/test/hotspot/jtreg/loongson/25064/NUMAHelper.java new file mode 100644 -index 00000000000..40443449bf3 +index 00000000000..ee0c4387eb3 --- /dev/null +++ b/test/hotspot/jtreg/loongson/25064/NUMAHelper.java -@@ -0,0 +1,99 @@ +@@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -81141,7 +82874,8 @@ index 00000000000..40443449bf3 + } + + static OutputAnalyzer invokeJvm(String... args) throws Exception { -+ return new OutputAnalyzer(ProcessTools.createTestJvm(args).start()); ++ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args); ++ return new OutputAnalyzer(pb.start()); + } + + static int getNUMANodes() throws Exception { @@ -82251,6 +83985,243 @@ index 00000000000..83ba5912879 + } + } +} +diff --git a/test/hotspot/jtreg/loongson/27950/Test27950.java b/test/hotspot/jtreg/loongson/27950/Test27950.java +new file mode 100644 +index 00000000000..da416bd5332 +--- /dev/null ++++ b/test/hotspot/jtreg/loongson/27950/Test27950.java +@@ -0,0 +1,231 @@ ++/* ++ * Copyright (c) 2023, Loongson Technology. 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. ++ * ++ */ ++ ++/** ++ * @test ++ * @summary Test whether A is enabled or disabled correctly. This test is ++ * divided into four groups: ++ * Group A: single/multi-core platform; ++ * Group B: single/multi-core platform, bind to 0 by taskset; ++ * Group C: multi-core platform, bind to 0-1 by taskset; ++ * Group D: single/multi-core platform, bind to 0 by numactl; ++ * Group E: multi-core platform, bind to 0-1 by numactl; ++ * each group containing six inputs: ++ * Input 1: -XX:-UseActiveCoresMP; ++ * Input 2: -XX:-UseActiveCoresMP, -XX:ActiveProcessorCount=1; ++ * Input 3: -XX:-UseActiveCoresMP, -XX:ActiveProcessorCount=2; ++ * Input 4: -XX:+UseActiveCoresMP; ++ * Input 5: -XX:+UseActiveCoresMP, -XX:ActiveProcessorCount=1; ++ * Input 6: -XX:+UseActiveCoresMP, -XX:ActiveProcessorCount=2; ++ * Input 7: [empty]; ++ * Input 8: -XX:ActiveProcessorCount=1; ++ * Input 9: -XX:ActiveProcessorCount=2; ++ * @library /test/lib ++ * @requires os.family == "linux" ++ * @requires os.arch == "loongarch64" ++ */ ++ ++import java.io.BufferedReader; ++import java.io.File; ++import java.io.InputStream; ++import java.io.InputStreamReader; ++import java.nio.charset.StandardCharsets; ++import java.util.ArrayList; ++import jdk.test.lib.process.OutputAnalyzer; ++import jdk.test.lib.process.ProcessTools; ++import jtreg.SkippedException; ++ ++public class Test27950 { ++ private static void testUseActiveCoresMP (ArrayList cmdLine, int physicalCoresNum, int availableCoresNum) throws Exception { ++ ProcessBuilder processBuilder = new ProcessBuilder(cmdLine); ++ OutputAnalyzer output = ProcessTools.executeProcess(processBuilder); ++ String warningMessage = "UseActiveCoresMP disabled because active processors are more than one."; ++ ++ if (physicalCoresNum == 1) { ++ if (!cmdLine.contains("-XX:-UseActiveCoresMP")) { ++ // Single-core machines are supposed to be permitted active cores ++ // optimization by default, or handcrafted. ++ output.shouldMatch("bool UseActiveCoresMP[ ]+= true"); ++ } else if (cmdLine.contains("-XX:-UseActiveCoresMP")) { ++ // Unless the flag is manually set to false via command line. ++ output.shouldMatch("bool UseActiveCoresMP[ ]+= false"); ++ } ++ } else { ++ if (availableCoresNum == 1 && cmdLine.contains("-XX:+UseActiveCoresMP")) { ++ // If cmdLine bound to processor 0 and the jvm args contains ++ // "-XX:+UseActiveCoresMP", the UseActiveCoresMP should be true. ++ output.shouldMatch("bool UseActiveCoresMP[ ]+= true"); ++ } else if (cmdLine.contains("-XX:+UseActiveCoresMP")) { ++ // Otherwise the UseActiveCoresMP should be false. But if the ++ // users set "+XX:UseActiveCoresMP", the JVM should change it ++ // to false, and print warning message on screen. ++ output.shouldContain(warningMessage); ++ output.shouldMatch("bool UseActiveCoresMP[ ]+= false"); ++ } else { ++ // In any other case, the UseActiveCoresMP should be false. ++ output.shouldMatch("bool UseActiveCoresMP[ ]+= false"); ++ } ++ } ++ } ++ ++ public static void groupTest (int physicalCoresNum, int availableCoresNum, int pos, String affiCmd, String affiArgs1, String affiArgs2) throws Exception { ++ ProcessBuilder master = ProcessTools.createLimitedTestJavaProcessBuilder(); ++ master.command().add("-XX:+PrintFlagsFinal"); ++ master.command().add("-version"); ++ ++ ArrayList cmdList = new ArrayList<>(master.command()); ++ if (affiCmd != null) { ++ cmdList.add(0, affiArgs2); ++ cmdList.add(0, affiArgs1); ++ cmdList.add(0, affiCmd); ++ } ++ ++ // Input 1: ++ // java -XX:-UseActiveCoresMP -XX:+PrintFlagsFinal -version ++ ArrayList test1 = new ArrayList<>(cmdList); ++ test1.add(pos, "-XX:-UseActiveCoresMP"); ++ testUseActiveCoresMP(test1, physicalCoresNum, availableCoresNum); ++ ++ // Input 2: ++ // java -XX:-UseActiveCoresMP -XX:ActiveProcessorCount=1 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test2 = new ArrayList<>(cmdList); ++ test2.add(pos, "-XX:-UseActiveCoresMP"); ++ test2.add(pos, "-XX:ActiveProcessorCount=1"); ++ testUseActiveCoresMP(test2, physicalCoresNum, availableCoresNum); ++ ++ // Input 3: ++ // java -XX:-UseActiveCoresMP -XX:ActiveProcessorCount=2 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test3 = new ArrayList<>(cmdList); ++ test3.add(pos, "-XX:-UseActiveCoresMP"); ++ test3.add(pos, "-XX:ActiveProcessorCount=2"); ++ testUseActiveCoresMP(test3, physicalCoresNum, availableCoresNum); ++ ++ // Input 4: ++ // java -XX:+UseActiveCoresMP -XX:+PrintFlagsFinal -version ++ ArrayList test4 = new ArrayList<>(cmdList); ++ test4.add(pos, "-XX:+UseActiveCoresMP"); ++ testUseActiveCoresMP(test4, physicalCoresNum, availableCoresNum); ++ ++ // Input 5: ++ // java -XX:+UseActiveCoresMP -XX:ActiveProcessorCount=1 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test5 = new ArrayList<>(cmdList); ++ test5.add(pos, "-XX:+UseActiveCoresMP"); ++ test5.add(pos, "-XX:ActiveProcessorCount=1"); ++ testUseActiveCoresMP(test5, physicalCoresNum, availableCoresNum); ++ ++ // Input 6: ++ // java -XX:+UseActiveCoresMP -XX:ActiveProcessorCount=2 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test6 = new ArrayList<>(cmdList); ++ test6.add(pos, "-XX:+UseActiveCoresMP"); ++ test6.add(pos, "-XX:ActiveProcessorCount=2"); ++ testUseActiveCoresMP(test6, physicalCoresNum, availableCoresNum); ++ ++ // Input 7: ++ // java -XX:+PrintFlagsFinal -version ++ ArrayList test7 = new ArrayList<>(cmdList); ++ testUseActiveCoresMP(test7, physicalCoresNum, availableCoresNum); ++ ++ // Input 8: ++ // java -XX:ActiveProcessorCount=1 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test8 = new ArrayList<>(cmdList); ++ test8.add(pos, "-XX:ActiveProcessorCount=1"); ++ testUseActiveCoresMP(test8, physicalCoresNum, availableCoresNum); ++ ++ // Input 9: ++ // java -XX:ActiveProcessorCount=2 ++ // -XX:+PrintFlagsFinal -version ++ ArrayList test9 = new ArrayList<>(cmdList); ++ test9.add(pos, "-XX:ActiveProcessorCount=2"); ++ testUseActiveCoresMP(test9, physicalCoresNum, availableCoresNum); ++ } ++ ++ public static void main (String... args) throws Exception { ++ int shellAvailableCoresNum = Runtime.getRuntime().availableProcessors(); ++ int availableCoresNum = shellAvailableCoresNum; ++ ++ boolean hasTaskset = true; ++ String taskset = null; ++ final String taskset1 = "/bin/taskset"; ++ final String taskset2 = "/usr/bin/taskset"; ++ if (new File(taskset1).exists()) { ++ taskset = taskset1; ++ } else if (new File(taskset2).exists()) { ++ taskset = taskset2; ++ } else { ++ hasTaskset = false; ++ } ++ ++ boolean hasNumactl = true; ++ String numactl = null; ++ final String numactl1 = "/bin/numactl"; ++ final String numactl2 = "/usr/bin/numactl"; ++ if (new File(numactl1).exists()) { ++ numactl = numactl1; ++ } else if (new File(numactl2).exists()) { ++ numactl = numactl2; ++ } else { ++ hasNumactl = false; ++ } ++ ++ int physicalCoresNum = -1; ++ ProcessBuilder processBuilder = new ProcessBuilder(); ++ processBuilder.command("sh", "-c", "cat /proc/cpuinfo | grep core | sort | uniq | wc -l"); ++ Process process = processBuilder.start(); ++ InputStream inputStream = process.getInputStream(); ++ InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); ++ char[] chs = new char[1024]; ++ int len = -1; ++ while ((len = inputStreamReader.read(chs)) != -1){ ++ String str = new String(chs, 0, len); ++ str = str.replaceAll("\r|\n", ""); ++ physicalCoresNum = Integer.valueOf(str).intValue(); ++ } ++ ++ // Group A: single/multi-core platform; ++ groupTest(physicalCoresNum, availableCoresNum, 1, null, null, null); ++ ++ if (hasTaskset) { ++ // Group B: single/multi-core platform, bind to 0 by taskset; ++ groupTest(physicalCoresNum, 1, 4, taskset, "-c", "0"); ++ if (physicalCoresNum > 1 && shellAvailableCoresNum != 1) { ++ // Group C: multi-core platform, bind to 0-1 by taskset; ++ groupTest(physicalCoresNum, 2, 4, taskset, "-c", "0-1"); ++ } ++ } ++ ++ if (hasNumactl) { ++ // Group D: single/multi-core platform, bind to 0 by numactl; ++ groupTest(physicalCoresNum, 1, 4, numactl, "-C", "0"); ++ if (physicalCoresNum > 1 && shellAvailableCoresNum != 1) { ++ // Group E: multi-core platform, bind to 0-1 by numactl; ++ groupTest(physicalCoresNum, 2, 4, numactl, "-C", "0-1"); ++ } ++ } ++ } ++} diff --git a/test/hotspot/jtreg/loongson/30358/MEMBARType.java b/test/hotspot/jtreg/loongson/30358/MEMBARType.java new file mode 100644 index 00000000000..71636057901 @@ -82328,7 +84299,7 @@ index 00000000000..9cfabdea488 +maxOutputSize = 2500000 diff --git a/test/hotspot/jtreg/loongson/30358/TestLoadLoad.java b/test/hotspot/jtreg/loongson/30358/TestLoadLoad.java new file mode 100644 -index 00000000000..29c3cebfece +index 00000000000..92a4f00c247 --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestLoadLoad.java @@ -0,0 +1,129 @@ @@ -82381,7 +84352,7 @@ index 00000000000..29c3cebfece + command.add("-XX:+PrintInterpreter"); + command.add("-version"); + -+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); @@ -82463,7 +84434,7 @@ index 00000000000..29c3cebfece +} diff --git a/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java b/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java new file mode 100644 -index 00000000000..a9a8cb39dca +index 00000000000..2bc9ada7ce8 --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java @@ -0,0 +1,247 @@ @@ -82539,7 +84510,7 @@ index 00000000000..a9a8cb39dca + command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test"); + command.add(Launcher.class.getName()); + -+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); @@ -82716,7 +84687,7 @@ index 00000000000..a9a8cb39dca +} diff --git a/test/hotspot/jtreg/loongson/30358/TestVolatile.java b/test/hotspot/jtreg/loongson/30358/TestVolatile.java new file mode 100644 -index 00000000000..ebe7ed7329a +index 00000000000..9fefa381c38 --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestVolatile.java @@ -0,0 +1,358 @@ @@ -82796,7 +84767,7 @@ index 00000000000..ebe7ed7329a + command.add("-XX:CompileCommand=dontinline," + Launcher.class.getName() + "::" + "*"); + command.add(Launcher.class.getName()); + -+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + @@ -83313,7 +85284,7 @@ index 5d9c3982fb6..f346e763db5 100644 * @requires vm.flagless * @library /test/lib diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java -index 6ad3f377706..cefd4e94811 100644 +index f77be989421..b4b050f00b7 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRMatching.java @@ -21,6 +21,12 @@ @@ -83567,6 +85538,210 @@ index 16863189500..e2f3a13473b 100644 + {"aix-ppc64", "dt_shmem"}, }; } +diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt +index 6e8953c521e..918edee9355 100644 +--- a/test/jdk/ProblemList-Xcomp.txt ++++ b/test/jdk/ProblemList-Xcomp.txt +@@ -21,6 +21,12 @@ + # questions. + # + ++# ++# This file has been modified by Loongson Technology in 2023. These ++# modifications are Copyright (c) 2020, 2023, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# ++ + ############################################################################# + # + # List of quarantined tests for testing in Xcomp mode. +@@ -30,3 +36,56 @@ + java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all + java/lang/management/MemoryMXBean/CollectionUsageThreshold.java 8318668 generic-all + com/sun/jdi/InterruptHangTest.java 8306679,8043571 generic-all ++ ++# loongson added ++com/sun/jndi/dns/ConfigTests/PortUnreachable.java generic-all ++com/sun/jndi/dns/ConfigTests/Timeout.java generic-loongarch64 ++com/sun/jndi/ldap/LdapCBPropertiesTest.java generic-loongarch64 ++com/sun/jndi/ldap/NamingExceptionMessageTest.java generic-all ++com/sun/net/httpserver/bugs/6725892/Test.java generic-loongarch64 ++com/sun/net/httpserver/bugs/B6393710.java generic-all ++com/sun/net/httpserver/bugs/B6401598.java generic-all ++com/sun/net/httpserver/bugs/B6433018.java generic-all ++com/sun/net/httpserver/bugs/B6529200.java generic-all ++com/sun/net/httpserver/Test10.java generic-all ++com/sun/net/httpserver/Test1.java generic-all ++java/net/httpclient/ManyRequests2.java generic-loongarch64 ++java/net/httpclient/MaxStreams.java generic-loongarch64 ++java/net/httpclient/TimeoutOrdering.java generic-loongarch64 ++java/net/Socket/DeadlockTest.java generic-loongarch64 ++java/net/Socket/RejectIPv6.java generic-loongarch64 ++java/net/URLConnection/ChunkedEncoding.java generic-loongarch64 ++java/net/URLConnection/ZeroContentLength.java generic-loongarch64 ++java/nio/channels/Channels/ReadXBytes.java generic-loongarch64 ++java/nio/channels/DatagramChannel/StressNativeSignal.java generic-loongarch64 ++java/nio/channels/FileChannel/LargeGatheringWrite.java generic-loongarch64 ++java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java generic-loongarch64 ++java/nio/file/Files/CheckPermissions.java #9588 generic-loongarch64 ++java/rmi/server/RemoteServer/AddrInUse.java generic-loongarch64 ++java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java generic-loongarch64 ++java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java generic-loongarch64 ++java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java generic-loongarch64 ++java/rmi/transport/acceptLoop/CloseServerSocketOnTermination.java generic-loongarch64 ++javax/net/ssl/ServerName/SSLSocketSNISensitive.java generic-loongarch64 ++javax/net/ssl/SSLSession/SessionTimeOutTests.java generic-loongarch64 ++javax/net/ssl/Stapling/HttpsUrlConnClient.java generic-loongarch64 ++javax/net/ssl/Stapling/SSLEngineWithStapling.java generic-loongarch64 ++javax/net/ssl/Stapling/SSLSocketWithStapling.java generic-loongarch64 ++javax/net/ssl/Stapling/StapleEnableProps.java generic-loongarch64 ++jdk/jfr/api/consumer/TestRecordedFullStackTrace.java generic-all ++jdk/jfr/api/metadata/eventtype/TestUnloadingEventClass.java generic-all ++jdk/jfr/event/compiler/TestCompilerInlining.java generic-all ++jdk/jfr/event/compiler/TestDeoptimization.java generic-all ++jdk/jfr/event/gc/stacktrace/TestMetaspaceSerialGCAllocationPendingStackTrace.java #25692 generic-loongarch64 ++jdk/jfr/event/io/TestInstrumentation.java #21678 generic-loongarch64 ++jdk/jfr/event/profiling/TestFullStackTrace.java generic-all ++sun/net/www/http/HttpClient/B8209178.java generic-all ++sun/net/www/protocol/http/AsyncDisconnect.java generic-loongarch64 ++sun/net/www/protocol/https/HttpsURLConnection/CookieHttpsClientTest.java generic-loongarch64 ++sun/security/krb5/auto/NullRenewUntil.java generic-loongarch64 ++sun/security/ssl/SignatureScheme/CustomizedClientSchemes.java generic-loongarch64 ++sun/security/ssl/SignatureScheme/CustomizedServerSchemes.java generic-loongarch64 ++sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS13.java generic-loongarch64 ++sun/security/ssl/SSLSocketImpl/SSLSocketBruceForceClose.java generic-loongarch64 ++sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java generic-loongarch64 ++sun/security/ssl/Stapling/StatusResponseManager.java generic-loongarch64 +diff --git a/test/jdk/ProblemList-jfx.txt b/test/jdk/ProblemList-jfx.txt +new file mode 100644 +index 00000000000..60e0ecd328c +--- /dev/null ++++ b/test/jdk/ProblemList-jfx.txt +@@ -0,0 +1,34 @@ ++# ++# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2022, Loongson Technology. 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. ++# ++ ++############################################################################# ++# ++# List of quarantined tests for testing with OpenJFX. ++# ++############################################################################# ++ ++############################################################################# ++# loongson added ++jdk/modules/etc/VerifyModuleDelegation.java #27845 generic-all ++tools/launcher/FXLauncherTest.java #27847 generic-all +diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt +index 9fae070e25d..5a5c1f3b556 100644 +--- a/test/jdk/ProblemList-zgc.txt ++++ b/test/jdk/ProblemList-zgc.txt +@@ -21,6 +21,12 @@ + # questions. + # + ++# ++# This file has been modified by Loongson Technology in 2023. These ++# modifications are Copyright (c) 2022, 2023, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# ++ + ############################################################################# + # + # List of quarantined tests for testing with ZGC. +@@ -29,3 +35,32 @@ + + sun/tools/jhsdb/JShellHeapDumpTest.java 8276539 generic-all + sun/tools/jhsdb/HeapDumpTestWithActiveProcess.java 8276539 generic-all ++ ++# loongson added ++com/sun/management/OperatingSystemMXBean/TestTotalSwap.java generic-x64 ++com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java generic-all ++com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java generic-all ++java/io/ObjectStreamClass/ObjectStreamClassCaching.java generic-loongarch64 ++java/net/InetAddress/HostsFileOrderingTest.java generic-all ++java/net/InetAddress/InternalNameServiceTest.java generic-all ++java/net/InetAddress/InternalNameServiceWithHostsFileTest.java generic-all ++java/nio/Buffer/DirectBufferAllocTest.java generic-loongarch64 ++java/time/test/java/time/format/TestZoneTextPrinterParser.java generic-loongarch64 ++javax/net/ssl/DTLSv10/DTLSv10BufferOverflowUnderflowTest.java generic-loongarch64 ++javax/net/ssl/DTLSv10/DTLSv10HandshakeTest.java generic-loongarch64 ++javax/net/ssl/DTLSv10/DTLSv10IncorrectAppDataTest.java generic-loongarch64 ++javax/net/ssl/sanity/interop/ClientJSSEServerJSSE.java generic-loongarch64 ++javax/net/ssl/TLS/TLSRehandshakeWithCipherChangeTest.java generic-loongarch64 ++javax/net/ssl/TLSv11/TLSDataExchangeTest.java generic-loongarch64 ++javax/net/ssl/TLSv11/TLSMFLNTest.java generic-loongarch64 ++javax/net/ssl/TLSv12/TLSEnginesClosureTest.java generic-loongarch64 ++javax/net/ssl/TLSv1/TLSHandshakeTest.java generic-loongarch64 ++javax/net/ssl/TLSv1/TLSMFLNTest.java generic-loongarch64 ++javax/net/ssl/TLSv1/TLSRehandshakeWithDataExTest.java generic-loongarch64 ++javax/xml/crypto/dsig/GenerationTests.java generic-loongarch64 ++jdk/incubator/vector/Byte256VectorTests.java generic-loongarch64 ++jdk/jfr/jcmd/TestJcmdStartWithSettings.java generic-x64 ++sun/security/ec/ed/EdDSATest.java generic-loongarch64 ++sun/security/ec/TestEC.java generic-loongarch64 ++sun/security/ec/xec/XECIterative.java generic-loongarch64 ++tools/jlink/CheckExecutable.java generic-all +diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt +index 47a8f09442e..1114bf990bd 100644 +--- a/test/jdk/ProblemList.txt ++++ b/test/jdk/ProblemList.txt +@@ -21,6 +21,12 @@ + # or visit www.oracle.com if you need additional information or have any + # questions. + # ++ ++# ++# This file has been modified by Loongson Technology in 2024. These ++# modifications are Copyright (c) 2019, 2024, Loongson Technology, and are made ++# available on the same license terms set forth above. ++# + ########################################################################### + # + # List of tests that should not be run by test/Makefile, for various reasons: +@@ -793,3 +799,22 @@ java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java 8256289 windo + java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all + java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-x64 + java/awt/Frame/SizeMinimizedTest.java 8305915 linux-x64 ++ ++# loongson added ++build/AbsPathsInImage.java #26391 generic-loongarch64 ++com/sun/net/httpserver/simpleserver/CommandLineNegativeTest.java #33051 generic-all ++com/sun/net/httpserver/simpleserver/CommandLinePositiveTest.java #33051 generic-all ++com/sun/net/httpserver/simpleserver/jwebserver/CommandLineNegativeTest.java #33051 generic-all ++com/sun/net/httpserver/simpleserver/jwebserver/CommandLinePositiveTest.java #33051 generic-all ++com/sun/net/httpserver/simpleserver/jwebserver/MaxRequestTimeTest.java #33051 generic-all ++com/sun/nio/sctp/SctpChannel/CloseDescriptors.java #31363 generic-all ++java/awt/font/GlyphVector/NLGlyphTest.java #21476 generic-loongarch64 ++javax/sound/sampled/Clip/SetPositionHang.java #26020 generic-loongarch64 ++jdk/jfr/event/gc/stacktrace/TestG1OldAllocationPendingStackTrace.java #25349 generic-loongarch64 ++security/infra/java/security/cert/CertPathValidator/certification/CertignaCA.java #33541 generic-all ++security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java #33541 generic-all ++security/infra/java/security/cert/CertPathValidator/certification/DigicertCSRootG5.java #33541 generic-all ++security/infra/java/security/cert/CertPathValidator/certification/EmSignRootG2CA.java #33541 generic-all ++security/infra/java/security/cert/CertPathValidator/certification/HaricaCA.java #33541 generic-all ++tools/launcher/HelpFlagsTest.java #33051 generic-all ++tools/launcher/VersionCheck.java #33051 generic-all diff --git a/test/jdk/java/foreign/callarranger/TestLoongArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestLoongArch64CallArranger.java new file mode 100644 index 00000000000..f4ebd42f612 @@ -84255,8 +86430,84 @@ index 37d770b62a5..1c3df61b8a7 100644 test("foo", "10.5.18.22", true, 5); test("theclub", "129.156.220.1", true, 6); +diff --git a/test/langtools/ProblemList-Xcomp.txt b/test/langtools/ProblemList-Xcomp.txt +new file mode 100644 +index 00000000000..3e41f660036 +--- /dev/null ++++ b/test/langtools/ProblemList-Xcomp.txt +@@ -0,0 +1,31 @@ ++# ++# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2021, 2022, Loongson Technology. 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. ++# ++ ++############################################################################# ++# loongson added ++jdk/jshell/JdiFailingLaunchExecutionControlTest.java #25693 generic-loongarch64 ++jdk/jshell/JdiFailingListenExecutionControlTest.java #25693 generic-loongarch64 ++jdk/jshell/JdiHangingLaunchExecutionControlTest.java generic-loongarch64 ++jdk/jshell/JdiHangingListenExecutionControlTest.java generic-loongarch64 ++jdk/jshell/ToolTabSnippetTest.java generic-all +diff --git a/test/langtools/ProblemList-zgc.txt b/test/langtools/ProblemList-zgc.txt +new file mode 100644 +index 00000000000..43d18e7097a +--- /dev/null ++++ b/test/langtools/ProblemList-zgc.txt +@@ -0,0 +1,33 @@ ++# ++# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2022, Loongson Technology. 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. ++# ++ ++############################################################################# ++# ++# List of quarantined tests for testing with ZGC. ++# ++############################################################################# ++ ++############################################################################# ++# loongson added ++jdk/internal/shellsupport/doc/JavadocHelperTest.java generic-all diff --git a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java -index f8ce856bddd..84b7ecba37f 100644 +index e78e200ac24..0a6abfd088f 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java @@ -33,6 +33,12 @@ @@ -84282,7 +86533,7 @@ index f8ce856bddd..84b7ecba37f 100644 OS("isAix", "isLinux", "isOSX", "isWindows"), VM_TYPE("isClient", "isServer", "isMinimal", "isZero", "isEmbedded"), diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java -index 92663c65d0f..311facd8ee1 100644 +index e2451fc8366..be0ecfd98aa 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -21,6 +21,12 @@ diff --git a/openjdk-latest.spec b/openjdk-latest.spec index b15c233..28be957 100644 --- a/openjdk-latest.spec +++ b/openjdk-latest.spec @@ -182,7 +182,7 @@ %global top_level_dir_name %{origin} %global minorver 0 %global buildver 11 -%global rpmrelease 3 +%global rpmrelease 4 # priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit %if %is_system_jdk %global priority %( printf '%02d%02d%02d%02d' %{majorver} %{minorver} %{securityver} %{buildver} ) @@ -1798,6 +1798,9 @@ cjc.mainProgram(args) -- the returns from copy_jdk_configs.lua should not affect %changelog +* Wed Aug 13 2025 Pan xuefeng - 1:23.0.1.11-4 +- LoongArch update to jdk23.0.1+11 + * Wed Mar 26 2025 Whitney33 - 1:23.0.1.11-3 - fix condigure arguments, disable global lto -- Gitee