diff --git a/8316859-RISC-V-Disable-detection-of-V-through-HWCAP.patch b/8316859-RISC-V-Disable-detection-of-V-through-HWCAP.patch deleted file mode 100644 index 95c3bfffc386f9d511e640e89ed8d6c1d0d454de..0000000000000000000000000000000000000000 --- a/8316859-RISC-V-Disable-detection-of-V-through-HWCAP.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 1013f0b0b911d24eed216485767ec6eb080afa81 Mon Sep 17 00:00:00 2001 -From: Ludovic Henry -Date: Mon, 25 Sep 2023 08:01:45 +0000 -Subject: [PATCH] 8316859: RISC-V: Disable detection of V through HWCAP - ---- - .../os_cpu/linux_riscv/vm_version_linux_riscv.cpp | 15 ++++++++++++--- - 1 file changed, 12 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp -index 454ffbb06d390..69bbf9f366b31 100644 ---- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp -@@ -149,12 +149,21 @@ void VM_Version::setup_cpu_available_features() { - - void VM_Version::os_aux_features() { - uint64_t auxv = getauxval(AT_HWCAP); -- int i = 0; -- while (_feature_list[i] != nullptr) { -+ for (int i = 0; _feature_list[i] != nullptr; i++) { -+ if (_feature_list[i]->feature_bit() == HWCAP_ISA_V) { -+ // Special case for V: some dev boards only support RVV version 0.7, while -+ // the OpenJDK only supports RVV version 1.0. These two versions are not -+ // compatible with each other. Given the V bit is set through HWCAP on -+ // some custom kernels, regardless of the version, it can lead to -+ // generating V instructions on boards that don't support RVV version 1.0 -+ // (ex: Sipeed LicheePi), leading to a SIGILL. -+ // That is an acceptable workaround as only Linux Kernel v6.5+ supports V, -+ // and that version already support hwprobe anyway -+ continue; -+ } - if ((_feature_list[i]->feature_bit() & auxv) != 0) { - _feature_list[i]->enable_feature(); - } -- i++; - } - } - diff --git a/8332854-Unable-to-build-openjdk-with-with-harfbuzz=system.patch b/8332854-Unable-to-build-openjdk-with-with-harfbuzz=system.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba23bf8b777ca64c09272dc14507fb49ddb054e9 --- /dev/null +++ b/8332854-Unable-to-build-openjdk-with-with-harfbuzz=system.patch @@ -0,0 +1,22 @@ +From ba5a4670b8ad86fefb41a939752754bf36aac9dc Mon Sep 17 00:00:00 2001 +From: Phil Race +Date: Mon, 17 Jun 2024 19:37:32 +0000 +Subject: [PATCH] 8332854: Unable to build openjdk with --with-harfbuzz=system + +Reviewed-by: jwaters, erikj, jdv, ihse +--- + make/modules/java.desktop/lib/ClientLibraries.gmk | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk +index 6f3616608ccea..f023969536987 100644 +--- a/make/modules/java.desktop/lib/ClientLibraries.gmk ++++ b/make/modules/java.desktop/lib/ClientLibraries.gmk +@@ -281,6 +281,7 @@ endif + ifeq ($(USE_EXTERNAL_HARFBUZZ), true) + LIBFONTMANAGER_EXTRA_SRC = + LIBFONTMANAGER_LIBS += $(HARFBUZZ_LIBS) ++ LIBFONTMANAGER_CFLAGS += $(HARFBUZZ_CFLAGS) + else + LIBFONTMANAGER_EXTRA_SRC = libharfbuzz + diff --git a/LoongArch64-support.patch b/LoongArch64-support.patch index 11de60aa94dd8e9e5ebe285b99e8809fdb4488a1..80a93bd3cadcedcf8ae2fc98b88c3a962204bad7 100644 --- a/LoongArch64-support.patch +++ b/LoongArch64-support.patch @@ -49,7 +49,7 @@ index 28801984862..c37c5c27429 100644 AC_MSG_RESULT([no, $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU]) AVAILABLE=false diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 -index 0c987e9e9ab..7b181d3cfc4 100644 +index df610cc489b..60492180191 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.m4 @@ -23,6 +23,12 @@ @@ -57,8 +57,8 @@ index 0c987e9e9ab..7b181d3cfc4 100644 # +# -+# This file has been modified by Loongson Technology in 2022. These -+# modifications are Copyright (c) 2018, 2022, Loongson Technology, and are made ++# This file has been modified by Loongson Technology in 2023. These ++# modifications are Copyright (c) 2018, 2023, Loongson Technology, and are made +# available on the same license terms set forth above. +# + @@ -86,8 +86,8 @@ index 0c987e9e9ab..7b181d3cfc4 100644 AC_SUBST(HOTSPOT_$1_CPU_ARCH) # Setup HOTSPOT_$1_CPU_DEFINE -@@ -571,6 +586,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], - HOTSPOT_$1_CPU_DEFINE=RISCV32 +@@ -569,6 +584,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], + HOTSPOT_$1_CPU_DEFINE=PPC64 elif test "x$OPENJDK_$1_CPU" = xriscv64; then HOTSPOT_$1_CPU_DEFINE=RISCV64 + elif test "x$OPENJDK_$1_CPU" = xloongarch64; then @@ -95,6 +95,15 @@ index 0c987e9e9ab..7b181d3cfc4 100644 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then +@@ -581,8 +598,6 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER], + HOTSPOT_$1_CPU_DEFINE=S390 + elif test "x$OPENJDK_$1_CPU" = xs390x; then + HOTSPOT_$1_CPU_DEFINE=S390 +- elif test "x$OPENJDK_$1_CPU" = xloongarch64; then +- HOTSPOT_$1_CPU_DEFINE=LOONGARCH64 + elif test "x$OPENJDK_$1_CPU" != x; then + HOTSPOT_$1_CPU_DEFINE=$(echo $OPENJDK_$1_CPU | tr a-z A-Z) + fi diff --git a/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp b/src/hotspot/cpu/loongarch/abstractInterpreter_loongarch.cpp new file mode 100644 index 00000000000..5423a479801 @@ -1084,10 +1093,10 @@ 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..c466efdb9e1 +index 00000000000..a4ee680663d --- /dev/null +++ b/src/hotspot/cpu/loongarch/assembler_loongarch.hpp -@@ -0,0 +1,3152 @@ +@@ -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. @@ -1245,7 +1254,7 @@ index 00000000000..c466efdb9e1 + assert_different_registers(_base, AT); + } + -+ Address(Register base, Register index, ScaleFactor scale, int disp = 0) ++ Address(Register base, Register index, ScaleFactor scale = no_scale, int disp = 0) + : _base (base), + _index(index), + _scale(scale), @@ -2060,6 +2069,10 @@ index 00000000000..c466efdb9e1 + vshuf_h_op = 0b01110001011110101, + vshuf_w_op = 0b01110001011110110, + vshuf_d_op = 0b01110001011110111, ++ vslti_b_op = 0b01110010100001100, ++ vslti_h_op = 0b01110010100001101, ++ vslti_w_op = 0b01110010100001110, ++ vslti_d_op = 0b01110010100001111, + vslti_bu_op = 0b01110010100010000, + vslti_hu_op = 0b01110010100010001, + vslti_wu_op = 0b01110010100010010, @@ -2236,6 +2249,10 @@ index 00000000000..c466efdb9e1 + xvshuf_w_op = 0b01110101011110110, + xvshuf_d_op = 0b01110101011110111, + xvperm_w_op = 0b01110101011111010, ++ xvslti_b_op = 0b01110110100001100, ++ xvslti_h_op = 0b01110110100001101, ++ xvslti_w_op = 0b01110110100001110, ++ xvslti_d_op = 0b01110110100001111, + xvslti_bu_op = 0b01110110100010000, + xvslti_hu_op = 0b01110110100010001, + xvslti_wu_op = 0b01110110100010010, @@ -2327,6 +2344,14 @@ index 00000000000..c466efdb9e1 + unknow_ops14 = 0b11111111111111 + }; + ++ // 13-bit opcode, highest 13 bits: bits[31...19] ++ enum ops13 { ++ vldrepl_d_op = 0b0011000000010, ++ xvldrepl_d_op = 0b0011001000010, ++ ++ unknow_ops13 = 0b1111111111111 ++ }; ++ + // 12-bit opcode, highest 12 bits: bits[31...20] + enum ops12 { + fmadd_s_op = 0b000010000001, @@ -2364,10 +2389,20 @@ index 00000000000..c466efdb9e1 + xvbitsel_v_op = 0b000011010010, + vshuf_b_op = 0b000011010101, + xvshuf_b_op = 0b000011010110, ++ vldrepl_w_op = 0b001100000010, ++ xvldrepl_w_op = 0b001100100010, + + unknow_ops12 = 0b111111111111 + }; + ++ // 11-bit opcode, highest 11 bits: bits[31...21] ++ enum ops11 { ++ vldrepl_h_op = 0b00110000010, ++ xvldrepl_h_op = 0b00110010010, ++ ++ unknow_ops11 = 0b11111111111 ++ }; ++ + // 10-bit opcode, highest 10 bits: bits[31...22] + enum ops10 { + bstr_w_op = 0b0000000001, @@ -2403,6 +2438,8 @@ index 00000000000..c466efdb9e1 + xvst_op = 0b0010110011, + ldl_w_op = 0b0010111000, + ldr_w_op = 0b0010111001, ++ vldrepl_b_op = 0b0011000010, ++ xvldrepl_b_op = 0b0011001010, + + unknow_ops10 = 0b1111111111 + }; @@ -2581,10 +2618,25 @@ index 00000000000..c466efdb9e1 + // | opcode | I8 | rj | rd | + static inline int insn_I8RR (int op, int imm8, int rj, int rd) { /*assert(is_simm(imm8, 8), "not a signed 8-bit int");*/ return (op<<18) | (low(imm8, 8)<<10) | (rj<<5) | rd; } + ++ // 2RI9-type ++ // 31 19 18 10 9 5 4 0 ++ // | opcode | I9 | rj | vd | ++ static inline int insn_I9RR(int op, int imm9, int rj, int vd) { return (op<<19) | (low(imm9, 9)<<10) | (rj<<5) | vd; } ++ ++ // 2RI10-type ++ // 31 20 19 10 9 5 4 0 ++ // | opcode | I10 | rj | vd | ++ static inline int insn_I10RR(int op, int imm10, int rj, int vd) { return (op<<20) | (low(imm10, 10)<<10) | (rj<<5) | vd; } ++ ++ // 2RI11-type ++ // 31 21 20 10 9 5 4 0 ++ // | opcode | I11 | rj | vd | ++ static inline int insn_I11RR(int op, int imm11, int rj, int vd) { return (op<<21) | (low(imm11, 11)<<10) | (rj<<5) | vd; } ++ + // 2RI12-type + // 31 22 21 10 9 5 4 0 + // | opcode | I12 | rj | rd | -+ static inline int insn_I12RR(int op, int imm12, int rj, int rd) { /* assert(is_simm(imm12, 12), "not a signed 12-bit int");*/ return (op<<22) | (low(imm12, 12)<<10) | (rj<<5) | rd; } ++ static inline int insn_I12RR(int op, int imm12, int rj, int rd) { return (op<<22) | (low(imm12, 12)<<10) | (rj<<5) | rd; } + + // 2RI14-type + // 31 24 23 10 9 5 4 0 @@ -3988,6 +4040,15 @@ index 00000000000..c466efdb9e1 + void xvslt_wu(FloatRegister xd, FloatRegister xj, FloatRegister xk) { ASSERT_LASX emit_int32(insn_RRR(xvslt_wu_op, (int)xk->encoding(), (int)xj->encoding(), (int)xd->encoding())); } + void xvslt_du(FloatRegister xd, FloatRegister xj, FloatRegister xk) { ASSERT_LASX emit_int32(insn_RRR(xvslt_du_op, (int)xk->encoding(), (int)xj->encoding(), (int)xd->encoding())); } + ++ void vslti_b(FloatRegister vd, FloatRegister vj, int si5) { ASSERT_LSX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR( vslti_b_op, si5, (int)vj->encoding(), (int)vd->encoding())); } ++ void vslti_h(FloatRegister vd, FloatRegister vj, int si5) { ASSERT_LSX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR( vslti_h_op, si5, (int)vj->encoding(), (int)vd->encoding())); } ++ void vslti_w(FloatRegister vd, FloatRegister vj, int si5) { ASSERT_LSX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR( vslti_w_op, si5, (int)vj->encoding(), (int)vd->encoding())); } ++ void vslti_d(FloatRegister vd, FloatRegister vj, int si5) { ASSERT_LSX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR( vslti_d_op, si5, (int)vj->encoding(), (int)vd->encoding())); } ++ void xvslti_b(FloatRegister xd, FloatRegister xj, int si5) { ASSERT_LASX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR(xvslti_b_op, si5, (int)xj->encoding(), (int)xd->encoding())); } ++ void xvslti_h(FloatRegister xd, FloatRegister xj, int si5) { ASSERT_LASX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR(xvslti_h_op, si5, (int)xj->encoding(), (int)xd->encoding())); } ++ void xvslti_w(FloatRegister xd, FloatRegister xj, int si5) { ASSERT_LASX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR(xvslti_w_op, si5, (int)xj->encoding(), (int)xd->encoding())); } ++ void xvslti_d(FloatRegister xd, FloatRegister xj, int si5) { ASSERT_LASX assert(is_simm(si5, 5), "not a signed 5-bit int"); emit_int32(insn_I5RR(xvslti_d_op, si5, (int)xj->encoding(), (int)xd->encoding())); } ++ + void vslti_bu(FloatRegister vd, FloatRegister vj, int ui5) { ASSERT_LSX emit_int32(insn_I5RR( vslti_bu_op, ui5, (int)vj->encoding(), (int)vd->encoding())); } + void vslti_hu(FloatRegister vd, FloatRegister vj, int ui5) { ASSERT_LSX emit_int32(insn_I5RR( vslti_hu_op, ui5, (int)vj->encoding(), (int)vd->encoding())); } + void vslti_wu(FloatRegister vd, FloatRegister vj, int ui5) { ASSERT_LSX emit_int32(insn_I5RR( vslti_wu_op, ui5, (int)vj->encoding(), (int)vd->encoding())); } @@ -4226,6 +4287,15 @@ index 00000000000..c466efdb9e1 + void vstx(FloatRegister vd, Register rj, Register rk) { ASSERT_LSX emit_int32(insn_RRR( vstx_op, (int)rk->encoding(), (int)rj->encoding(), (int)vd->encoding())); } + void xvstx(FloatRegister xd, Register rj, Register rk) { ASSERT_LASX emit_int32(insn_RRR(xvstx_op, (int)rk->encoding(), (int)rj->encoding(), (int)xd->encoding())); } + ++ void vldrepl_d(FloatRegister vd, Register rj, int si9) { ASSERT_LSX assert(is_simm(si9, 9), "not a signed 9-bit int"); emit_int32(insn_I9RR( vldrepl_d_op, si9, (int)rj->encoding(), (int)vd->encoding()));} ++ void vldrepl_w(FloatRegister vd, Register rj, int si10) { ASSERT_LSX assert(is_simm(si10, 10), "not a signed 10-bit int"); emit_int32(insn_I10RR( vldrepl_w_op, si10, (int)rj->encoding(), (int)vd->encoding()));} ++ void vldrepl_h(FloatRegister vd, Register rj, int si11) { ASSERT_LSX assert(is_simm(si11, 11), "not a signed 11-bit int"); emit_int32(insn_I11RR( vldrepl_h_op, si11, (int)rj->encoding(), (int)vd->encoding()));} ++ void vldrepl_b(FloatRegister vd, Register rj, int si12) { ASSERT_LSX assert(is_simm(si12, 12), "not a signed 12-bit int"); emit_int32(insn_I12RR( vldrepl_b_op, si12, (int)rj->encoding(), (int)vd->encoding()));} ++ void xvldrepl_d(FloatRegister xd, Register rj, int si9) { ASSERT_LASX assert(is_simm(si9, 9), "not a signed 9-bit int"); emit_int32(insn_I9RR(xvldrepl_d_op, si9, (int)rj->encoding(), (int)xd->encoding()));} ++ void xvldrepl_w(FloatRegister xd, Register rj, int si10) { ASSERT_LASX assert(is_simm(si10, 10), "not a signed 10-bit int"); emit_int32(insn_I10RR(xvldrepl_w_op, si10, (int)rj->encoding(), (int)xd->encoding()));} ++ void xvldrepl_h(FloatRegister xd, Register rj, int si11) { ASSERT_LASX assert(is_simm(si11, 11), "not a signed 11-bit int"); emit_int32(insn_I11RR(xvldrepl_h_op, si11, (int)rj->encoding(), (int)xd->encoding()));} ++ void xvldrepl_b(FloatRegister xd, Register rj, int si12) { ASSERT_LASX assert(is_simm(si12, 12), "not a signed 12-bit int"); emit_int32(insn_I12RR(xvldrepl_b_op, si12, (int)rj->encoding(), (int)xd->encoding()));} ++ +#undef ASSERT_LSX +#undef ASSERT_LASX + @@ -5454,10 +5524,10 @@ 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..f522c7de66b +index 00000000000..1cea5b84c0f --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_LIRAssembler_loongarch_64.cpp -@@ -0,0 +1,3369 @@ +@@ -0,0 +1,3365 @@ +/* + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -6749,9 +6819,8 @@ index 00000000000..f522c7de66b + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); + } + -+ Label profile_cast_success, profile_cast_failure; -+ Label *success_target = should_profile ? &profile_cast_success : success; -+ Label *failure_target = should_profile ? &profile_cast_failure : failure; ++ Label* success_target = success; ++ Label* failure_target = failure; + + if (obj == k_RInfo) { + k_RInfo = dst; @@ -6769,16 +6838,26 @@ index 00000000000..f522c7de66b + + if (should_profile) { + Label not_null; -+ __ bnez(obj, not_null); -+ // Object is null; update MDO and exit + Register mdo = klass_RInfo; + __ mov_metadata(mdo, md->constant_encoding()); ++ __ bnez(obj, not_null); ++ // Object is null; update MDO and exit + Address data_addr = Address(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset())); + __ ld_bu(SCR2, data_addr); + __ ori(SCR2, SCR2, BitData::null_seen_byte_constant()); + __ st_b(SCR2, data_addr); + __ b(*obj_is_null); + __ bind(not_null); ++ ++ Label update_done; ++ Register recv = k_RInfo; ++ __ load_klass(recv, obj); ++ type_profile_helper(mdo, md, data, recv, &update_done); ++ Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); ++ __ ld_d(SCR2, counter_addr); ++ __ addi_d(SCR2, SCR2, DataLayout::counter_increment); ++ __ st_d(SCR2, counter_addr); ++ __ bind(update_done); + } else { + __ beqz(obj, *obj_is_null); + } @@ -6838,23 +6917,6 @@ index 00000000000..f522c7de66b + // successful cast, fall through to profile or jump + } + } -+ if (should_profile) { -+ Register mdo = klass_RInfo, recv = k_RInfo; -+ __ bind(profile_cast_success); -+ __ mov_metadata(mdo, md->constant_encoding()); -+ __ load_klass(recv, obj); -+ Label update_done; -+ type_profile_helper(mdo, md, data, recv, success); -+ __ b(*success); -+ -+ __ bind(profile_cast_failure); -+ __ mov_metadata(mdo, md->constant_encoding()); -+ Address counter_addr = Address(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); -+ __ ld_d(SCR2, counter_addr); -+ __ addi_d(SCR2, SCR2, -DataLayout::counter_increment); -+ __ st_d(SCR2, counter_addr); -+ __ b(*failure); -+ } + __ b(*success); +} + @@ -6884,22 +6946,32 @@ index 00000000000..f522c7de66b + assert(data != nullptr, "need data for type check"); + assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); + } -+ Label profile_cast_success, profile_cast_failure, done; -+ Label *success_target = should_profile ? &profile_cast_success : &done; -+ Label *failure_target = should_profile ? &profile_cast_failure : stub->entry(); ++ Label done; ++ Label* success_target = &done; ++ Label* failure_target = stub->entry(); + + if (should_profile) { + Label not_null; -+ __ bnez(value, not_null); -+ // Object is null; update MDO and exit + Register mdo = klass_RInfo; + __ mov_metadata(mdo, md->constant_encoding()); ++ __ bnez(value, not_null); ++ // Object is null; update MDO and exit + Address data_addr = Address(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset())); + __ ld_bu(SCR2, data_addr); + __ ori(SCR2, SCR2, BitData::null_seen_byte_constant()); + __ st_b(SCR2, data_addr); + __ b(done); + __ bind(not_null); ++ ++ Label update_done; ++ Register recv = k_RInfo; ++ __ load_klass(recv, value); ++ type_profile_helper(mdo, md, data, recv, &update_done); ++ Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); ++ __ ld_d(SCR2, counter_addr); ++ __ addi_d(SCR2, SCR2, DataLayout::counter_increment); ++ __ st_d(SCR2, counter_addr); ++ __ bind(update_done); + } else { + __ beqz(value, done); + } @@ -6924,25 +6996,6 @@ index 00000000000..f522c7de66b + __ beqz(k_RInfo, *failure_target); + // fall through to the success case + -+ if (should_profile) { -+ Register mdo = klass_RInfo, recv = k_RInfo; -+ __ bind(profile_cast_success); -+ __ mov_metadata(mdo, md->constant_encoding()); -+ __ load_klass(recv, value); -+ Label update_done; -+ type_profile_helper(mdo, md, data, recv, &done); -+ __ b(done); -+ -+ __ bind(profile_cast_failure); -+ __ mov_metadata(mdo, md->constant_encoding()); -+ Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); -+ __ lea(SCR2, counter_addr); -+ __ ld_d(SCR1, Address(SCR2)); -+ __ addi_d(SCR1, SCR1, -DataLayout::counter_increment); -+ __ st_d(SCR1, Address(SCR2)); -+ __ b(*stub->entry()); -+ } -+ + __ bind(done); + } else if (code == lir_checkcast) { + Register obj = op->object()->as_register(); @@ -6984,7 +7037,6 @@ index 00000000000..f522c7de66b +} + +void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { -+ assert(VM_Version::supports_cx8(), "wrong machine"); + Register addr; + if (op->addr()->is_register()) { + addr = as_reg(op->addr()); @@ -8454,7 +8506,10 @@ index 00000000000..f522c7de66b + __ verify_oop(obj); + + if (tmp != obj) { ++ assert_different_registers(obj, tmp, SCR1, SCR2, mdo_addr.base(), mdo_addr.index()); + __ move(tmp, obj); ++ } else { ++ assert_different_registers(obj, SCR1, SCR2, mdo_addr.base(), mdo_addr.index()); + } + if (do_null) { + __ bnez(tmp, update); @@ -8513,10 +8568,11 @@ index 00000000000..f522c7de66b + __ beqz(SCR2, none); + __ li(SCR1, (u1)TypeEntries::null_seen); + __ beq(SCR2, SCR1, none); -+ // There is a chance that the checks above (re-reading profiling -+ // data from memory) fail if another thread has just set the ++ // There is a chance that the checks above ++ // fail if another thread has just set the + // profiling to this obj's klass + membar_acquire(); ++ __ XOR(tmp, tmp, SCR2); // get back original value before XOR + __ ld_d(SCR2, mdo_addr); + __ XOR(tmp, tmp, SCR2); + assert(TypeEntries::type_klass_mask == -4, "must be"); @@ -8543,6 +8599,11 @@ index 00000000000..f522c7de66b + __ bind(none); + // first time here. Set profile type. + __ st_d(tmp, mdo_addr); ++#ifdef ASSERT ++ assert(TypeEntries::type_mask == -2, "must be"); ++ __ bstrpick_d(tmp, tmp, 63, 1); ++ __ verify_klass_ptr(tmp); ++#endif + } + } else { + // There's a single possible klass at this profile point @@ -8576,6 +8637,11 @@ index 00000000000..f522c7de66b +#endif + // first time here. Set profile type. + __ st_d(tmp, mdo_addr); ++#ifdef ASSERT ++ assert(TypeEntries::type_mask == -2, "must be"); ++ __ bstrpick_d(tmp, tmp, 63, 1); ++ __ verify_klass_ptr(tmp); ++#endif + } else { + assert(ciTypeEntries::valid_ciklass(current_klass) != nullptr && + ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); @@ -8829,13 +8895,13 @@ index 00000000000..f522c7de66b +#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..c11f0318415 +index 00000000000..bf5fba7a100 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_LIRGenerator_loongarch_64.cpp -@@ -0,0 +1,1391 @@ +@@ -0,0 +1,1393 @@ +/* + * Copyright (c) 2005, 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 @@ -8992,8 +9058,10 @@ index 00000000000..c11f0318415 + if (index->is_register()) { + // apply the shift and accumulate the displacement + if (shift > 0) { -+ LIR_Opr tmp = new_pointer_register(); -+ __ shift_left(index, shift, tmp); ++ // Use long register to avoid overflow when shifting large index values left. ++ LIR_Opr tmp = new_register(T_LONG); ++ __ convert(Bytecodes::_i2l, index, tmp); ++ __ shift_left(tmp, shift, tmp); + index = tmp; + } + if (large_disp != 0) { @@ -10521,7 +10589,7 @@ 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..681dbf09e8c +index 00000000000..eaaaf464fe6 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_MacroAssembler_loongarch_64.cpp @@ -0,0 +1,350 @@ @@ -10588,7 +10656,7 @@ index 00000000000..681dbf09e8c + // Load object header + ld_d(hdr, Address(obj, hdr_offset)); + if (LockingMode == LM_LIGHTWEIGHT) { -+ fast_lock(obj, hdr, SCR1, SCR2, slow_case); ++ lightweight_lock(obj, hdr, SCR1, SCR2, slow_case); + } else if (LockingMode == LM_LEGACY) { + Label done; + // and mark it as unlocked @@ -10652,7 +10720,7 @@ index 00000000000..681dbf09e8c + // be encoded. + andi(AT, hdr, markWord::monitor_value); + bnez(AT, slow_case); -+ fast_unlock(obj, hdr, SCR1, SCR2, 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 + // the displaced header in the object - if the object header is not pointing to @@ -10877,10 +10945,10 @@ index 00000000000..681dbf09e8c +#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..aaef45bc4f1 +index 00000000000..21f7c6f2d00 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c1_Runtime1_loongarch_64.cpp -@@ -0,0 +1,1041 @@ +@@ -0,0 +1,1049 @@ +/* + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -11354,6 +11422,14 @@ index 00000000000..aaef45bc4f1 + const Register exception_pc = A1; + const Register handler_addr = A3; + ++ if (AbortVMOnException) { ++ __ enter(); ++ save_live_registers(sasm); ++ __ call_VM_leaf(CAST_FROM_FN_PTR(address, check_abort_on_vm_exception), A0); ++ restore_live_registers(sasm); ++ __ leave(); ++ } ++ + // verify that only A0, is valid at this time + __ invalidate_registers(false, true, true, true, true, true); + @@ -11994,7 +12070,7 @@ index 00000000000..a97091dda04 +#endif // CPU_LOONGARCH_C1_GLOBALS_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/c2_CodeStubs_loongarch.cpp b/src/hotspot/cpu/loongarch/c2_CodeStubs_loongarch.cpp new file mode 100644 -index 00000000000..4672c7b08a8 +index 00000000000..37b74d4ac16 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c2_CodeStubs_loongarch.cpp @@ -0,0 +1,91 @@ @@ -12054,7 +12130,7 @@ index 00000000000..4672c7b08a8 + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); -+ __ call_long(StubRoutines::la::method_entry_barrier()); ++ __ call_long(StubRoutines::method_entry_barrier()); + __ b(continuation()); + + __ bind(guard()); @@ -12091,10 +12167,10 @@ index 00000000000..4672c7b08a8 +#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..c2bca9bb765 +index 00000000000..d83d08e9549 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.cpp -@@ -0,0 +1,1716 @@ +@@ -0,0 +1,1903 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -12190,7 +12266,7 @@ index 00000000000..c2bca9bb765 + b(cont); + } else { + assert(LockingMode == LM_LIGHTWEIGHT, "must be"); -+ fast_lock(oop, disp_hdr, flag, SCR1, no_count); ++ lightweight_lock(oop, disp_hdr, flag, SCR1, no_count); + b(count); + } + @@ -12267,7 +12343,7 @@ index 00000000000..c2bca9bb765 + b(cont); + } else { + assert(LockingMode == LM_LIGHTWEIGHT, "must be"); -+ fast_unlock(oop, tmp, flag, box, no_count); ++ lightweight_unlock(oop, tmp, flag, box, no_count); + b(count); + } + @@ -12990,17 +13066,21 @@ index 00000000000..c2bca9bb765 +// 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) { -+ Label L, Loop, LoopEnd, HaveResult, Done; ++ 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); @@ -13009,10 +13089,190 @@ index 00000000000..c2bca9bb765 + sub_d(result, cnt1, cnt2); // result holds the difference of two lengths + + // compute the shorter length (in cnt1) -+ ori(AT, R0, charsInWord); -+ bge(cnt2, cnt1, Loop); ++ bge(cnt2, cnt1, V_Start); + move(cnt1, cnt2); + ++ 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); ++ xvinsgr2vr_d(fscratch, tmp1, 2); ++ 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); ++ } ++ } ++ + // Now the shorter length is in cnt1 and cnt2 can be used as a tmp register + // + // For example: @@ -13026,6 +13286,9 @@ index 00000000000..c2bca9bb765 + // + // 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); + blt(cnt1, AT, LoopEnd); + if (isLL) { @@ -13813,10 +14076,10 @@ index 00000000000..c2bca9bb765 +} 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..5e54bd84183 +index 00000000000..804e060f195 --- /dev/null +++ b/src/hotspot/cpu/loongarch/c2_MacroAssembler_loongarch.hpp -@@ -0,0 +1,140 @@ +@@ -0,0 +1,141 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -13860,7 +14123,8 @@ index 00000000000..5e54bd84183 + // Compare strings. + void string_compare(Register str1, Register str2, + Register cnt1, Register cnt2, Register result, -+ int ae, Register tmp1, Register tmp2); ++ int ae, Register tmp1, Register tmp2, ++ FloatRegister vtmp1, FloatRegister vtmp2); + + // Find index of char in Latin-1 string + void stringL_indexof_char(Register str1, Register cnt1, @@ -14316,6 +14580,89 @@ index 00000000000..17ee4b75f72 +} + +#endif // !PRODUCT +diff --git a/src/hotspot/cpu/loongarch/compressedKlass_loongarch.cpp b/src/hotspot/cpu/loongarch/compressedKlass_loongarch.cpp +new file mode 100644 +index 00000000000..b42bac14cd8 +--- /dev/null ++++ b/src/hotspot/cpu/loongarch/compressedKlass_loongarch.cpp +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2023, Red Hat, Inc. All rights reserved. ++ * Copyright (c) 2023, 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. ++ * ++ */ ++ ++#include "precompiled.hpp" ++#include "oops/compressedKlass.hpp" ++#include "utilities/globalDefinitions.hpp" ++ ++char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size_t size, bool aslr, bool optimize_for_zero_base) { ++ ++ char* result = nullptr; ++ ++ // LoongArch loads a 64-bit immediate in up to four separate steps, splitting it into four different sections ++ // (two 32-bit sections, each split into two subsections of 20/12 bits). ++ // ++ // 63 ....... 52 51 ... 32 31 ....... 12 11 ... 0 ++ // D C B A ++ // ++ // A "good" base is, in this order: ++ // 1) only bits in A; this would be an address < 4KB, which is unrealistic on normal Linux boxes since ++ // the typical default for vm.mmap_min_address is 64KB. We ignore that. ++ // 2) only bits in B: a 12-bit-aligned address below 4GB. 12 bit = 4KB, but since mmap reserves at ++ // page boundaries, we can ignore the alignment. ++ // 3) only bits in C: a 4GB-aligned address that is lower than 4PB. ++ // 4) only bits in D: a 4PB-aligned address. ++ ++ // First, attempt to allocate < 4GB. We do this unconditionally: ++ // - if can_optimize_for_zero_base, a <4GB mapping start would allow us to run unscaled (base = 0, shift = 0) ++ // - if !can_optimize_for_zero_base, a <4GB mapping start is still good, the resulting immediate can be encoded ++ // with one instruction (2) ++ result = reserve_address_space_for_unscaled_encoding(size, aslr); ++ ++ // Failing that, attempt to reserve for base=zero shift>0 ++ if (result == nullptr && optimize_for_zero_base) { ++ result = reserve_address_space_for_zerobased_encoding(size, aslr); ++ } ++ ++ // Failing that, optimize for case (3) - a base with only bits set between [33-52) ++ if (result == nullptr) { ++ const uintptr_t from = nth_bit(32 + (optimize_for_zero_base ? LogKlassAlignmentInBytes : 0)); ++ constexpr uintptr_t to = nth_bit(52); ++ constexpr size_t alignment = nth_bit(32); ++ result = reserve_address_space_X(from, to, size, alignment, aslr); ++ } ++ ++ // Failing that, optimize for case (4) - a base with only bits set between [52-64) ++ if (result == nullptr) { ++ constexpr uintptr_t from = nth_bit(52); ++ constexpr uintptr_t to = UINT64_MAX; ++ constexpr size_t alignment = nth_bit(52); ++ result = reserve_address_space_X(from, to, size, alignment, aslr); ++ } ++ ++ return result; ++} diff --git a/src/hotspot/cpu/loongarch/continuationEntry_loongarch.hpp b/src/hotspot/cpu/loongarch/continuationEntry_loongarch.hpp new file mode 100644 index 00000000000..c2d91996000 @@ -14415,10 +14762,10 @@ index 00000000000..d1c01ee42f0 +#endif // CPU_LOONGARCH_CONTINUATIONENTRY_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/continuationFreezeThaw_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/continuationFreezeThaw_loongarch.inline.hpp new file mode 100644 -index 00000000000..c4c49842464 +index 00000000000..3743fff2f14 --- /dev/null +++ b/src/hotspot/cpu/loongarch/continuationFreezeThaw_loongarch.inline.hpp -@@ -0,0 +1,284 @@ +@@ -0,0 +1,272 @@ +/* + * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -14504,7 +14851,7 @@ index 00000000000..c4c49842464 + intptr_t *sp, *fp; // sp is really our unextended_sp + if (FKind::interpreted) { + assert((intptr_t*)f.at(frame::interpreter_frame_last_sp_offset) == nullptr -+ || f.unextended_sp() == (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset), ""); ++ || f.unextended_sp() == (intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset), ""); + intptr_t locals_offset = *f.addr_at(frame::interpreter_frame_locals_offset); + // If the caller.is_empty(), i.e. we're freezing into an empty chunk, then we set + // the chunk's argsize in finalize_freeze and make room for it above the unextended_sp @@ -14543,31 +14890,23 @@ index 00000000000..c4c49842464 + +void FreezeBase::adjust_interpreted_frame_unextended_sp(frame& f) { + assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) || (f.unextended_sp() == f.sp()), ""); -+ intptr_t* real_unextended_sp = (intptr_t*)f.at(frame::interpreter_frame_last_sp_offset); ++ intptr_t* real_unextended_sp = (intptr_t*)f.at_relative_or_null(frame::interpreter_frame_last_sp_offset); + if (real_unextended_sp != nullptr) { + f.set_unextended_sp(real_unextended_sp); // can be null at a safepoint + } +} + -+static inline void relativize_one(intptr_t* const vfp, intptr_t* const hfp, int offset) { -+ assert(*(hfp + offset) == *(vfp + offset), ""); -+ intptr_t* addr = hfp + offset; -+ intptr_t value = *(intptr_t**)addr - vfp; -+ *addr = value; -+} -+ +inline void FreezeBase::relativize_interpreted_frame_metadata(const frame& f, const frame& hf) { -+ intptr_t* vfp = f.fp(); -+ intptr_t* hfp = hf.fp(); -+ assert(hfp == hf.unextended_sp() + (f.fp() - f.unextended_sp()), ""); ++ assert(hf.fp() == hf.unextended_sp() + (f.fp() - f.unextended_sp()), ""); + assert((f.at(frame::interpreter_frame_last_sp_offset) != 0) + || (f.unextended_sp() == f.sp()), ""); -+ assert(f.fp() > (intptr_t*)f.at(frame::interpreter_frame_initial_sp_offset), ""); ++ assert(f.fp() > (intptr_t*)f.at_relative(frame::interpreter_frame_initial_sp_offset), ""); + -+ // at(frame::interpreter_frame_last_sp_offset) can be null at safepoint preempts -+ *hf.addr_at(frame::interpreter_frame_last_sp_offset) = hf.unextended_sp() - hf.fp(); ++ // Make sure that last_sp is already relativized. ++ assert((intptr_t*)hf.at_relative(frame::interpreter_frame_last_sp_offset) == hf.unextended_sp(), ""); + -+ relativize_one(vfp, hfp, frame::interpreter_frame_initial_sp_offset); // == block_top == block_bottom ++ // Make sure that monitor_block_top is already relativized. ++ assert(hf.at_absolute(frame::interpreter_frame_monitor_block_top_offset) <= frame::interpreter_frame_initial_sp_offset, ""); + + assert((hf.fp() - hf.unextended_sp()) == (f.fp() - f.unextended_sp()), ""); + assert(hf.unextended_sp() == (intptr_t*)hf.at(frame::interpreter_frame_last_sp_offset), ""); @@ -14631,7 +14970,7 @@ index 00000000000..c4c49842464 + intptr_t* heap_sp = hf.unextended_sp(); + // If caller is interpreted it already made room for the callee arguments + int overlap = caller.is_interpreted_frame() ? ContinuationHelper::InterpretedFrame::stack_argsize(hf) : 0; -+ const int fsize = ContinuationHelper::InterpretedFrame::frame_bottom(hf) - hf.unextended_sp() - overlap; ++ const int fsize = (int)(ContinuationHelper::InterpretedFrame::frame_bottom(hf) - hf.unextended_sp() - overlap); + const int locals = hf.interpreter_frame_method()->max_locals(); + intptr_t* frame_sp = caller.unextended_sp() - fsize; + intptr_t* fp = frame_sp + (hf.fp() - heap_sp); @@ -14690,25 +15029,21 @@ index 00000000000..c4c49842464 + patch_callee_link(caller, caller.fp()); +} + -+static inline void derelativize_one(intptr_t* const fp, int offset) { -+ intptr_t* addr = fp + offset; -+ *addr = (intptr_t)(fp + *addr); -+} -+ +inline void ThawBase::derelativize_interpreted_frame_metadata(const frame& hf, const frame& f) { -+ intptr_t* vfp = f.fp(); ++ // Make sure that last_sp is kept relativized. ++ assert((intptr_t*)f.at_relative(frame::interpreter_frame_last_sp_offset) == f.unextended_sp(), ""); + -+ derelativize_one(vfp, frame::interpreter_frame_last_sp_offset); -+ derelativize_one(vfp, frame::interpreter_frame_initial_sp_offset); ++ // Make sure that monitor_block_top is still relativized. ++ assert(f.at_absolute(frame::interpreter_frame_monitor_block_top_offset) <= frame::interpreter_frame_initial_sp_offset, ""); +} + +#endif // CPU_LOONGARCH_CONTINUATIONFREEZETHAW_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/continuationHelper_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/continuationHelper_loongarch.inline.hpp new file mode 100644 -index 00000000000..b36584a968a +index 00000000000..8c0aff579f9 --- /dev/null +++ b/src/hotspot/cpu/loongarch/continuationHelper_loongarch.inline.hpp -@@ -0,0 +1,145 @@ +@@ -0,0 +1,146 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -14833,11 +15168,12 @@ index 00000000000..b36584a968a + // interpreter_frame_last_sp_offset, points to unextended_sp includes arguments in the frame + // interpreter_frame_initial_sp_offset excludes expression stack slots + int expression_stack_sz = expression_stack_size(f, mask); -+ intptr_t* res = *(intptr_t**)f.addr_at(frame::interpreter_frame_initial_sp_offset) - expression_stack_sz; ++ intptr_t* res = (intptr_t*)f.at_relative(frame::interpreter_frame_initial_sp_offset) - expression_stack_sz; + assert(res == (intptr_t*)f.interpreter_frame_monitor_end() - expression_stack_sz, ""); + assert(res >= f.unextended_sp(), + "res: " INTPTR_FORMAT " initial_sp: " INTPTR_FORMAT " last_sp: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " expression_stack_size: %d", -+ p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at(frame::interpreter_frame_last_sp_offset), p2i(f.unextended_sp()), expression_stack_sz); ++ p2i(res), p2i(f.addr_at(frame::interpreter_frame_initial_sp_offset)), f.at_relative_or_null(frame::interpreter_frame_last_sp_offset), ++ p2i(f.unextended_sp()), expression_stack_sz); + return res; +} + @@ -15135,10 +15471,10 @@ index 00000000000..6fdd1bd1915 +#endif // CPU_LOONGARCH_DISASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/downcallLinker_loongarch_64.cpp b/src/hotspot/cpu/loongarch/downcallLinker_loongarch_64.cpp new file mode 100644 -index 00000000000..4f936060b6b +index 00000000000..5a5c49bf46e --- /dev/null +++ b/src/hotspot/cpu/loongarch/downcallLinker_loongarch_64.cpp -@@ -0,0 +1,360 @@ +@@ -0,0 +1,366 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -15177,63 +15513,6 @@ index 00000000000..4f936060b6b + +#define __ _masm-> + -+class DowncallStubGenerator : public StubCodeGenerator { -+ BasicType* _signature; -+ int _num_args; -+ BasicType _ret_bt; -+ const ABIDescriptor& _abi; -+ -+ const GrowableArray& _input_registers; -+ const GrowableArray& _output_registers; -+ -+ bool _needs_return_buffer; -+ int _captured_state_mask; -+ bool _needs_transition; -+ -+ int _frame_complete; -+ int _frame_size_slots; -+ OopMapSet* _oop_maps; -+public: -+ DowncallStubGenerator(CodeBuffer* buffer, -+ BasicType* signature, -+ int num_args, -+ BasicType ret_bt, -+ const ABIDescriptor& abi, -+ const GrowableArray& input_registers, -+ const GrowableArray& output_registers, -+ bool needs_return_buffer, -+ int captured_state_mask, -+ bool needs_transition) -+ : StubCodeGenerator(buffer, PrintMethodHandleStubs), -+ _signature(signature), -+ _num_args(num_args), -+ _ret_bt(ret_bt), -+ _abi(abi), -+ _input_registers(input_registers), -+ _output_registers(output_registers), -+ _needs_return_buffer(needs_return_buffer), -+ _captured_state_mask(captured_state_mask), -+ _needs_transition(needs_transition), -+ _frame_complete(0), -+ _frame_size_slots(0), -+ _oop_maps(nullptr) { -+ } -+ -+ void generate(); -+ -+ int frame_complete() const { -+ return _frame_complete; -+ } -+ -+ int framesize() const { -+ return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt)); -+ } -+ -+ OopMapSet* oop_maps() const { -+ return _oop_maps; -+ } -+}; -+ +static const int native_invoker_code_base_size = 256; +static const int native_invoker_size_per_arg = 8; + @@ -15249,19 +15528,29 @@ index 00000000000..4f936060b6b + int code_size = native_invoker_code_base_size + (num_args * native_invoker_size_per_arg); + int locs_size = 1; // must be non-zero + CodeBuffer code("nep_invoker_blob", code_size, locs_size); -+ DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, -+ input_registers, output_registers, -+ needs_return_buffer, captured_state_mask, -+ needs_transition); ++ if (code.blob() == nullptr) { ++ return nullptr; ++ } ++ StubGenerator g(&code, signature, num_args, ret_bt, abi, ++ input_registers, output_registers, ++ needs_return_buffer, captured_state_mask, ++ needs_transition); + g.generate(); + code.log_section_sizes("nep_invoker_blob"); + ++ bool caller_must_gc_arguments = false; ++ bool alloc_fail_is_fatal = false; + RuntimeStub* stub = + RuntimeStub::new_runtime_stub("nep_invoker_blob", + &code, + g.frame_complete(), + g.framesize(), -+ g.oop_maps(), false); ++ g.oop_maps(), ++ caller_must_gc_arguments, ++ alloc_fail_is_fatal); ++ if (stub == nullptr) { ++ return nullptr; ++ } + +#ifndef PRODUCT + LogTarget(Trace, foreign, downcall) lt; @@ -15275,7 +15564,36 @@ index 00000000000..4f936060b6b + return stub; +} + -+void DowncallStubGenerator::generate() { ++static constexpr int FP_BIAS = 0; // sender_sp_offset is 0 on RISCV ++ ++void DowncallLinker::StubGenerator::pd_add_offset_to_oop(VMStorage reg_oop, VMStorage reg_offset, VMStorage tmp1, VMStorage tmp2) const { ++ Register r_tmp1 = as_Register(tmp1); ++ Register r_tmp2 = as_Register(tmp2); ++ if (reg_oop.is_reg()) { ++ assert(reg_oop.type() == StorageType::INTEGER, "expected"); ++ Register reg_oop_reg = as_Register(reg_oop); ++ if (reg_offset.is_reg()) { ++ assert(reg_offset.type() == StorageType::INTEGER, "expected"); ++ __ add_d(reg_oop_reg, reg_oop_reg, as_Register(reg_offset)); ++ } else { ++ assert(reg_offset.is_stack(), "expected"); ++ assert(reg_offset.stack_size() == 8, "expected long"); ++ __ ld_d(r_tmp1, Address(FP, FP_BIAS + reg_offset.offset())); ++ __ add_d(reg_oop_reg, reg_oop_reg, r_tmp1); ++ } ++ } else { ++ assert(reg_oop.is_stack(), "expected"); ++ assert(reg_oop.stack_size() == 8, "expected long"); ++ assert(reg_offset.is_stack(), "expected"); ++ assert(reg_offset.stack_size() == 8, "expected long"); ++ __ ld_d(r_tmp1, Address(FP, FP_BIAS + reg_offset.offset())); ++ __ ld_d(r_tmp2, Address(FP, FP_BIAS + reg_oop.offset())); ++ __ add_d(r_tmp1, r_tmp2, r_tmp1); ++ __ st_d(r_tmp1, Address(FP, FP_BIAS + reg_oop.offset())); ++ } ++} ++ ++void DowncallLinker::StubGenerator::generate() { + enum layout { + fp_off, + fp_off2, @@ -15290,23 +15608,16 @@ index 00000000000..4f936060b6b + Register tmp1 = SCR1; + Register tmp2 = SCR2; + -+ VMStorage shuffle_reg = as_VMStorage(S0); -+ JavaCallingConvention in_conv; -+ NativeCallingConvention out_conv(_input_registers); -+ ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg); -+ -+#ifndef PRODUCT -+ LogTarget(Trace, foreign, downcall) lt; -+ if (lt.is_enabled()) { -+ ResourceMark rm; -+ LogStream ls(lt); -+ arg_shuffle.print_on(&ls); -+ } -+#endif ++ GrowableArray java_regs; ++ ForeignGlobals::java_calling_convention(_signature, _num_args, java_regs); ++ bool has_objects = false; ++ GrowableArray filtered_java_regs = ForeignGlobals::downcall_filter_offset_regs(java_regs, _signature, ++ _num_args, has_objects); ++ assert(!(_needs_transition && has_objects), "can not pass objects when doing transition"); + + int allocated_frame_size = 0; + assert(_abi._shadow_space_bytes == 0, "not expecting shadow space on LoongArch64"); -+ allocated_frame_size += arg_shuffle.out_arg_bytes(); ++ allocated_frame_size += ForeignGlobals::compute_out_arg_bytes(_input_registers); + + bool should_save_return_value = !_needs_return_buffer; + RegSpiller out_reg_spiller(_output_registers); @@ -15333,6 +15644,33 @@ index 00000000000..4f936060b6b + allocated_frame_size += BytesPerWord; + } + ++ // The space we have allocated will look like: ++ // ++ // FP-> | | ++ // |---------------------| = frame_bottom_offset = frame_size ++ // | (optional) | ++ // | capture state buf | ++ // |---------------------| = StubLocations::CAPTURED_STATE_BUFFER ++ // | (optional) | ++ // | return buffer | ++ // |---------------------| = StubLocations::RETURN_BUFFER ++ // SP-> | out/stack args | or | out_reg_spiller area | ++ // ++ // Note how the last chunk can be shared, since the 3 uses occur at different times. ++ ++ VMStorage shuffle_reg = as_VMStorage(S0); ++ GrowableArray out_regs = ForeignGlobals::replace_place_holders(_input_registers, locs); ++ ArgumentShuffle arg_shuffle(filtered_java_regs, out_regs, shuffle_reg); ++ ++#ifndef PRODUCT ++ LogTarget(Trace, foreign, downcall) lt; ++ if (lt.is_enabled()) { ++ ResourceMark rm; ++ LogStream ls(lt); ++ arg_shuffle.print_on(&ls); ++ } ++#endif ++ + _frame_size_slots = align_up(framesize + (allocated_frame_size >> LogBytesPerInt), 4); + assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned"); + @@ -15364,8 +15702,12 @@ index 00000000000..4f936060b6b + } + } + ++ if (has_objects) { ++ add_offsets_to_oops(java_regs, as_VMStorage(tmp1), as_VMStorage(tmp2)); ++ } ++ + __ block_comment("{ argument shuffle"); -+ arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs); ++ arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes); + __ block_comment("} argument shuffle"); + + __ jalr(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); @@ -15501,10 +15843,10 @@ index 00000000000..4f936060b6b +} diff --git a/src/hotspot/cpu/loongarch/foreignGlobals_loongarch.cpp b/src/hotspot/cpu/loongarch/foreignGlobals_loongarch.cpp new file mode 100644 -index 00000000000..c0837e64d80 +index 00000000000..b31a03b3427 --- /dev/null +++ b/src/hotspot/cpu/loongarch/foreignGlobals_loongarch.cpp -@@ -0,0 +1,195 @@ +@@ -0,0 +1,187 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -15669,21 +16011,13 @@ index 00000000000..c0837e64d80 + } +} + -+void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { ++void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias) const { + Register tmp_reg = as_Register(tmp); + for (int i = 0; i < _moves.length(); i++) { + Move move = _moves.at(i); + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; + -+ // replace any placeholders -+ if (from_reg.type() == StorageType::PLACEHOLDER) { -+ from_reg = locs.get(from_reg); -+ } -+ if (to_reg.type() == StorageType::PLACEHOLDER) { -+ to_reg = locs.get(to_reg); -+ } -+ + switch (from_reg.type()) { + case StorageType::INTEGER: + assert(from_reg.segment_mask() == REG64_MASK, "only 64-bit register supported"); @@ -15758,10 +16092,10 @@ 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..93aaa623344 +index 00000000000..09703c9d7c4 --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.cpp -@@ -0,0 +1,626 @@ +@@ -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. @@ -16079,7 +16413,7 @@ index 00000000000..93aaa623344 +} + +BasicObjectLock* frame::interpreter_frame_monitor_end() const { -+ BasicObjectLock* result = (BasicObjectLock*) at(interpreter_frame_monitor_block_top_offset); ++ BasicObjectLock* result = (BasicObjectLock*) at_relative(interpreter_frame_monitor_block_top_offset); + // make sure the pointer points inside the frame + assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer"); + assert((intptr_t*) result < fp(), "monitor end should be strictly below the frame pointer"); @@ -16087,12 +16421,17 @@ index 00000000000..93aaa623344 +} + +void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { -+ *((BasicObjectLock**)addr_at(interpreter_frame_monitor_block_top_offset)) = value; ++ assert(is_interpreted_frame(), "interpreted frame expected"); ++ // set relativized monitor_block_top ++ ptr_at_put(interpreter_frame_monitor_block_top_offset, (intptr_t*)value - fp()); ++ assert(at_absolute(interpreter_frame_monitor_block_top_offset) <= interpreter_frame_monitor_block_top_offset, ""); +} + +// Used by template based interpreter deoptimization -+void frame::interpreter_frame_set_last_sp(intptr_t* sp) { -+ *((intptr_t**)addr_at(interpreter_frame_last_sp_offset)) = sp; ++void frame::interpreter_frame_set_last_sp(intptr_t* last_sp) { ++ assert(is_interpreted_frame(), "interpreted frame expected"); ++ // set relativized last_sp ++ ptr_at_put(interpreter_frame_last_sp_offset, last_sp != nullptr ? (last_sp - fp()) : 0); +} + +frame frame::sender_for_entry_frame(RegisterMap* map) const { @@ -16243,7 +16582,7 @@ index 00000000000..93aaa623344 + + // first the method + -+ Method* m = *interpreter_frame_method_addr(); ++ Method* m = safe_interpreter_frame_method(); + + // validate the method we'd find in this potential sender + if (!Method::is_valid_method(m)) return false; @@ -16390,7 +16729,7 @@ index 00000000000..93aaa623344 +} diff --git a/src/hotspot/cpu/loongarch/frame_loongarch.hpp b/src/hotspot/cpu/loongarch/frame_loongarch.hpp new file mode 100644 -index 00000000000..a8f775718a9 +index 00000000000..36dd89ff08f --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.hpp @@ -0,0 +1,200 @@ @@ -16493,8 +16832,8 @@ index 00000000000..a8f775718a9 + // Entry frames + // n.b. these values are determined by the layout defined in + // stubGenerator for the Java call stub -+ entry_frame_after_call_words = 25, -+ entry_frame_call_wrapper_offset = -11, ++ entry_frame_after_call_words = 23, ++ entry_frame_call_wrapper_offset = -3, + + // we don't need a save area + arg_reg_save_area_bytes = 0, @@ -16596,10 +16935,10 @@ index 00000000000..a8f775718a9 +#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..a740b3b1df3 +index 00000000000..8eac47d6ef9 --- /dev/null +++ b/src/hotspot/cpu/loongarch/frame_loongarch.inline.hpp -@@ -0,0 +1,472 @@ +@@ -0,0 +1,473 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -16632,7 +16971,6 @@ index 00000000000..a740b3b1df3 +#include "code/codeCache.inline.hpp" +#include "code/vmreg.inline.hpp" +#include "interpreter/interpreter.hpp" -+#include "interpreter/oopMapCache.hpp" +#include "runtime/sharedRuntime.hpp" + +// Inline functions for Loongson frames: @@ -16826,7 +17164,7 @@ index 00000000000..a740b3b1df3 + +inline int frame::frame_size() const { + return is_interpreted_frame() -+ ? sender_sp() - sp() ++ ? pointer_delta_as_int(sender_sp(), sp()) + : cb()->frame_size(); +} + @@ -16853,7 +17191,9 @@ index 00000000000..a740b3b1df3 +} + +inline intptr_t* frame::interpreter_frame_last_sp() const { -+ return (intptr_t*)at(interpreter_frame_last_sp_offset); ++ intptr_t n = *addr_at(interpreter_frame_last_sp_offset); ++ assert(n <= 0, "n: " INTPTR_FORMAT, n); ++ return n != 0 ? &fp()[n] : nullptr; +} + +inline intptr_t* frame::interpreter_frame_bcp_addr() const { @@ -17685,7 +18025,7 @@ 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..8b45eb5131c +index 00000000000..12ef43b5a83 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shared/barrierSetAssembler_loongarch.cpp @@ -0,0 +1,453 @@ @@ -18085,7 +18425,7 @@ index 00000000000..8b45eb5131c + Label skip_barrier; + __ beq(SCR1, SCR2, skip_barrier); + -+ __ call_long(StubRoutines::la::method_entry_barrier()); ++ __ call_long(StubRoutines::method_entry_barrier()); + __ b(skip_barrier); + + __ bind(local_guard); @@ -18953,10 +19293,10 @@ 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..62db2bc609f +index 00000000000..d9377db5503 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoahBarrierSetAssembler_loongarch.cpp -@@ -0,0 +1,781 @@ +@@ -0,0 +1,783 @@ +/* + * Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -19434,7 +19774,7 @@ index 00000000000..62db2bc609f + assert_different_registers(addr.base(), expected, tmp1, tmp2); + assert_different_registers(addr.base(), new_val, tmp1, tmp2); + -+ Label step4, done_succ, done_fail, done; ++ Label step4, done_succ, done_fail, done, is_null; + + // There are two ways to reach this label. Initial entry into the + // cmpxchg_oop code expansion starts at step1 (which is equivalent @@ -19503,13 +19843,15 @@ index 00000000000..62db2bc609f + __ move(tmp1, tmp2); + + if (is_narrow) { ++ __ beqz(tmp1, is_null); + // Decode tmp1 in order to resolve its forward pointer -+ __ decode_heap_oop(tmp1); -+ } -+ resolve_forward_pointer(masm, tmp1); -+ if (is_narrow) { ++ __ decode_heap_oop_not_null(tmp1); ++ resolve_forward_pointer_not_null(masm, tmp1); + // Encode tmp1 to compare against expected. -+ __ encode_heap_oop(tmp1); ++ __ encode_heap_oop_not_null(tmp1); ++ __ bind(is_null); ++ } else { ++ resolve_forward_pointer(masm, tmp1); + } + + // Does forwarded value of fetched from-space pointer match original @@ -19834,7 +20176,7 @@ 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..8dc0ce5a62b +index 00000000000..2608ef13576 --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/shenandoah/shenandoah_loongarch_64.ad @@ -0,0 +1,232 @@ @@ -19869,16 +20211,16 @@ index 00000000000..8dc0ce5a62b +%} + +encode %{ -+ enc_class loongarch_enc_cmpxchg_oop_shenandoah(memory mem, mRegP oldval, mRegP newval, mRegI res) %{ ++ enc_class loongarch_enc_cmpxchg_oop_shenandoah(indirect mem, mRegP oldval, mRegP newval, mRegI res) %{ + MacroAssembler _masm(&cbuf); -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + 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(memory mem, mRegP oldval, mRegP newval, mRegI res) %{ ++ 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), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} @@ -19904,7 +20246,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} @@ -19932,7 +20274,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} @@ -19948,7 +20290,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ true, $res$$Register); + %} @@ -19964,7 +20306,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ true, $res$$Register); + %} @@ -19980,7 +20322,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ true, $res$$Register); + %} @@ -19996,7 +20338,7 @@ index 00000000000..8dc0ce5a62b + %} + + ins_encode %{ -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ true, $res$$Register); + %} @@ -20012,7 +20354,7 @@ index 00000000000..8dc0ce5a62b + %} + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} @@ -20029,7 +20371,7 @@ index 00000000000..8dc0ce5a62b + + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ false, /*is_cae*/ false, $res$$Register); + %} @@ -20046,7 +20388,7 @@ index 00000000000..8dc0ce5a62b + + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} @@ -20063,7 +20405,7 @@ index 00000000000..8dc0ce5a62b + + ins_encode %{ + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop -+ Address addr(as_Register($mem$$base), $mem$$disp); ++ Address addr(as_Register($mem$$base), 0); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, addr, $oldval$$Register, $newval$$Register, + /*acquire*/ true, /*is_cae*/ false, $res$$Register); + %} @@ -20917,7 +21259,7 @@ 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..fdb66075606 +index 00000000000..c4e77f08b4f --- /dev/null +++ b/src/hotspot/cpu/loongarch/gc/x/x_loongarch_64.ad @@ -0,0 +1,256 @@ @@ -20979,12 +21321,12 @@ index 00000000000..fdb66075606 + // Weak CAS operations are thus only emitted if the barrier is elided. + Address addr(mem); + if (node->barrier_data() == XLoadBarrierElided) { -+ __ cmpxchg(addr, oldval, newval, tmp, false /* retold */, acquire /* barrier */, ++ __ cmpxchg(addr, oldval, newval, tmp, false /* retold */, acquire /* acquire */, + weak /* weak */, false /* exchange */); + __ move(res, tmp); + } else { + __ move(tmp, oldval); -+ __ cmpxchg(addr, tmp, newval, AT, true /* retold */, acquire /* barrier */, ++ __ cmpxchg(addr, tmp, newval, AT, true /* retold */, acquire /* acquire */, + false /* weak */, false /* exchange */); + __ move(res, AT); + @@ -20993,7 +21335,7 @@ index 00000000000..fdb66075606 + __ andr(AT, AT, tmp); + __ beqz(AT, good); + x_load_barrier_slow_path(_masm, node, addr, tmp, res /* used as tmp */); -+ __ cmpxchg(addr, oldval, newval, tmp, false /* retold */, acquire /* barrier */, weak /* weak */, false /* exchange */); ++ __ cmpxchg(addr, oldval, newval, tmp, false /* retold */, acquire /* acquire */, weak /* weak */, false /* exchange */); + __ move(res, tmp); + __ bind(good); + } @@ -23101,10 +23443,10 @@ 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..196d7057b0e +index 00000000000..2306c5bc6d1 --- /dev/null +++ b/src/hotspot/cpu/loongarch/globalDefinitions_loongarch.hpp -@@ -0,0 +1,55 @@ +@@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -23136,6 +23478,7 @@ index 00000000000..196d7057b0e +const int BytesPerInstWord = 4; + +const int StackAlignmentInBytes = (2*wordSize); ++const size_t pd_segfault_address = 1024; + +// Indicates whether the C calling conventions require that +// 32-bit integer argument values are properly extended to 64 bits. @@ -23159,6 +23502,8 @@ index 00000000000..196d7057b0e + +#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY + ++#define DEFAULT_CACHE_LINE_SIZE 64 ++ +#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 @@ -23476,10 +23821,10 @@ index 00000000000..3a180549fc6 +#endif // CPU_LOONGARCH_ICACHE_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp b/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp new file mode 100644 -index 00000000000..a632f7b881e +index 00000000000..85bed067c49 --- /dev/null +++ b/src/hotspot/cpu/loongarch/interp_masm_loongarch.hpp -@@ -0,0 +1,272 @@ +@@ -0,0 +1,271 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -23596,13 +23941,12 @@ index 00000000000..a632f7b881e + } + + void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset); -+ void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2)); -+ void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); + void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); + void get_method_counters(Register method, Register mcs, Label& skip); + + void load_resolved_indy_entry(Register cache, Register index); ++ void load_field_entry(Register cache, Register index, int bcp_offset = 1); ++ void load_method_entry(Register cache, Register index, int bcp_offset = 1); + + // load cpool->resolved_references(index); + void load_resolved_reference_at_index(Register result, Register index, Register tmp); @@ -23637,7 +23981,8 @@ index 00000000000..a632f7b881e + void push(TosState state); // transition state -> vtos + + void empty_expression_stack() { -+ ld_d(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ ld_d(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ alsl_d(SP, AT, FP, LogBytesPerWord-1); + // null last_sp until next java call + st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); + } @@ -23706,15 +24051,14 @@ index 00000000000..a632f7b881e + Label& not_equal_continue); + + void record_klass_in_profile(Register receiver, Register mdp, -+ Register reg2, bool is_virtual_call); ++ Register reg2); + void record_klass_in_profile_helper(Register receiver, Register mdp, + Register reg2, int start_row, -+ Label& done, bool is_virtual_call); -+ ++ Label& done); + void record_item_in_profile_helper(Register item, Register mdp, + Register reg2, int start_row, Label& done, int total_rows, -+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, -+ int non_profiled_offset); ++ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn); ++ + void update_mdp_by_offset(Register mdp_in, int offset_of_offset); + void update_mdp_by_offset(Register mdp_in, Register reg, int offset_of_disp); + void update_mdp_by_constant(Register mdp_in, int constant); @@ -23754,10 +24098,10 @@ index 00000000000..a632f7b881e +#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..07be00ace59 +index 00000000000..0e9e66940b4 --- /dev/null +++ b/src/hotspot/cpu/loongarch/interp_masm_loongarch_64.cpp -@@ -0,0 +1,1957 @@ +@@ -0,0 +1,1884 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -23791,8 +24135,11 @@ index 00000000000..07be00ace59 +#include "interpreter/interpreterRuntime.hpp" +#include "oops/arrayOop.hpp" +#include "oops/markWord.hpp" -+#include "oops/methodData.hpp" +#include "oops/method.hpp" ++#include "oops/methodData.hpp" ++#include "oops/resolvedFieldEntry.hpp" ++#include "oops/resolvedIndyEntry.hpp" ++#include "oops/resolvedMethodEntry.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" @@ -24014,63 +24361,6 @@ index 00000000000..07be00ace59 + } +} + -+ -+void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, -+ Register index, -+ int bcp_offset, -+ size_t index_size) { -+ assert_different_registers(cache, index); -+ get_cache_index_at_bcp(index, bcp_offset, index_size); -+ ld_d(cache, FP, frame::interpreter_frame_cache_offset * wordSize); -+ assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); -+ assert(exact_log2(in_words(ConstantPoolCacheEntry::size())) == 2, "else change next line"); -+ slli_d(index, index, 2); -+} -+ -+ -+void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache, -+ Register index, -+ Register bytecode, -+ int byte_no, -+ int bcp_offset, -+ size_t index_size) { -+ get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size); -+ // We use a 32-bit load here since the layout of 64-bit words on -+ // little-endian machines allow us that. -+ alsl_d(AT, index, cache, Address::times_ptr - 1); -+ ld_w(bytecode, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::indices_offset())); -+ if(os::is_MP()) { -+ membar(Assembler::Membar_mask_bits(LoadLoad|LoadStore)); -+ } -+ -+ const int shift_count = (1 + byte_no) * BitsPerByte; -+ assert((byte_no == TemplateTable::f1_byte && shift_count == ConstantPoolCacheEntry::bytecode_1_shift) || -+ (byte_no == TemplateTable::f2_byte && shift_count == ConstantPoolCacheEntry::bytecode_2_shift), -+ "correct shift count"); -+ srli_d(bytecode, bytecode, shift_count); -+ assert(ConstantPoolCacheEntry::bytecode_1_mask == ConstantPoolCacheEntry::bytecode_2_mask, "common mask"); -+ li(AT, ConstantPoolCacheEntry::bytecode_1_mask); -+ andr(bytecode, bytecode, AT); -+} -+ -+void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, -+ Register tmp, -+ int bcp_offset, -+ size_t index_size) { -+ assert(bcp_offset > 0, "bcp is still pointing to start of bytecode"); -+ assert(cache != tmp, "must use different register"); -+ get_cache_index_at_bcp(tmp, bcp_offset, index_size); -+ assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below"); -+ // convert from field index to ConstantPoolCacheEntry index -+ // and from word offset to byte offset -+ assert(exact_log2(in_bytes(ConstantPoolCacheEntry::size_in_bytes())) == 2 + LogBytesPerWord, "else change next line"); -+ slli_d(tmp, tmp, 2 + LogBytesPerWord); -+ ld_d(cache, FP, frame::interpreter_frame_cache_offset * wordSize); -+ // skip past the header -+ addi_d(cache, cache, in_bytes(ConstantPoolCache::base_offset())); -+ add_d(cache, cache, tmp); -+} -+ +void InterpreterMacroAssembler::get_method_counters(Register method, + Register mcs, Label& skip) { + Label has_counters; @@ -24089,12 +24379,42 @@ index 00000000000..07be00ace59 + // Get address of invokedynamic array + ld_d(cache, FP, frame::interpreter_frame_cache_offset * wordSize); + ld_d(cache, Address(cache, in_bytes(ConstantPoolCache::invokedynamic_entries_offset()))); -+ // Scale the index to be the entry index * sizeof(ResolvedInvokeDynamicInfo) ++ // Scale the index to be the entry index * sizeof(ResolvedIndyEntry) + slli_d(index, index, log2i_exact(sizeof(ResolvedIndyEntry))); + addi_d(cache, cache, Array::base_offset_in_bytes()); + add_d(cache, cache, index); +} + ++void InterpreterMacroAssembler::load_field_entry(Register cache, Register index, int bcp_offset) { ++ // Get index out of bytecode pointer ++ get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); ++ // Take shortcut if the size is a power of 2 ++ if (is_power_of_2(sizeof(ResolvedFieldEntry))) { ++ slli_d(index, index, log2i_exact(sizeof(ResolvedFieldEntry))); // Scale index by power of 2 ++ } else { ++ li(cache, sizeof(ResolvedFieldEntry)); ++ mul_d(index, index, cache); // Scale the index to be the entry index * sizeof(ResolvedIndyEntry) ++ } ++ ld_d(cache, FP, frame::interpreter_frame_cache_offset * wordSize); ++ // Get address of field entries array ++ ld_d(cache, Address(cache, ConstantPoolCache::field_entries_offset())); ++ addi_d(cache, cache, Array::base_offset_in_bytes()); ++ add_d(cache, cache, index); ++} ++ ++void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) { ++ // Get index out of bytecode pointer ++ get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); ++ li(cache, sizeof(ResolvedMethodEntry)); ++ mul_d(index, index, cache); // Scale the index to be the entry index * sizeof(ResolvedMethodEntry) ++ ++ ld_d(cache, FP, frame::interpreter_frame_cache_offset * wordSize); ++ // Get address of field entries array ++ ld_d(cache, Address(cache, ConstantPoolCache::method_entries_offset())); ++ addi_d(cache, cache, Array::base_offset_in_bytes()); ++ add_d(cache, cache, index); ++} ++ +// Load object from cpool->resolved_references(index) +void InterpreterMacroAssembler::load_resolved_reference_at_index( + Register result, Register index, Register tmp) { @@ -24121,19 +24441,6 @@ index 00000000000..07be00ace59 + ld_d(klass, AT, Array::base_offset_in_bytes()); +} + -+void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no, -+ Register method, -+ Register cache, -+ Register index) { -+ const int method_offset = in_bytes( -+ ConstantPoolCache::base_offset() + -+ ((byte_no == TemplateTable::f2_byte) -+ ? ConstantPoolCacheEntry::f2_offset() -+ : ConstantPoolCacheEntry::f1_offset())); -+ -+ ld_d(method, Address(cache, index, Address::times_ptr, method_offset)); // get f1 Method* -+} -+ +// Resets LVP to locals. Register sub_klass cannot be any of the above. +void InterpreterMacroAssembler::gen_subtype_check( Register Rsup_klass, Register Rsub_klass, Label &ok_is_subtype ) { + @@ -24146,10 +24453,6 @@ index 00000000000..07be00ace59 + + // Do the check. + check_klass_subtype(Rsub_klass, Rsup_klass, T1, ok_is_subtype); // blows T1 -+ -+ // Profile the failure of the check. -+ profile_typecheck_failed(T4); // blows T4 -+ +} + + @@ -24259,7 +24562,9 @@ index 00000000000..07be00ace59 + // set sender sp + move(Rsender, SP); + // record last_sp -+ st_d(SP, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ sub_d(AT, SP, FP); ++ srai_d(AT, AT, Interpreter::logStackElementSize); ++ st_d(AT, FP, frame::interpreter_frame_last_sp_offset * wordSize); +} + +// Jump to from_interpreted entry of a call unless single stepping is possible @@ -24466,13 +24771,14 @@ index 00000000000..07be00ace59 + // Check that all monitors are unlocked + { + Label loop, exception, entry, restart; -+ const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; ++ const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); + const Address monitor_block_top(FP, + frame::interpreter_frame_monitor_block_top_offset * wordSize); + + bind(restart); + // points to current entry, starting with top-most entry + ld_d(monitor_reg, monitor_block_top); ++ alsl_d(monitor_reg, monitor_reg, FP, LogBytesPerWord-1); + // points to word before bottom of monitor block, should be callee-saved + addi_d(TSR, FP, frame::interpreter_frame_initial_sp_offset * wordSize); + b(entry); @@ -24529,6 +24835,12 @@ index 00000000000..07be00ace59 + // testing if reserved zone needs to be re-enabled + Label no_reserved_zone_enabling; + ++ // check if already enabled - if so no re-enabling needed ++ assert(sizeof(StackOverflow::StackGuardState) == 4, "unexpected size"); ++ ld_w(AT, Address(TREG, JavaThread::stack_guard_state_offset())); ++ addi_w(AT, AT, StackOverflow::stack_guard_enabled); ++ beqz(AT, no_reserved_zone_enabling); ++ + ld_d(AT, Address(TREG, JavaThread::reserved_stack_activation_offset())); + bge(AT, Rsender, no_reserved_zone_enabling); + @@ -24582,7 +24894,7 @@ index 00000000000..07be00ace59 + + if (LockingMode == LM_LIGHTWEIGHT) { + ld_d(tmp_reg, Address(scr_reg, oopDesc::mark_offset_in_bytes())); -+ fast_lock(scr_reg, tmp_reg, SCR1, SCR2, slow_case); ++ lightweight_lock(scr_reg, tmp_reg, SCR1, SCR2, slow_case); + b(count); + } else if (LockingMode == LM_LEGACY) { + // Load (object->mark() | 1) into tmp_reg @@ -24683,7 +24995,7 @@ index 00000000000..07be00ace59 + ld_d(hdr_reg, Address(scr_reg, oopDesc::mark_offset_in_bytes())); + andi(AT, hdr_reg, markWord::monitor_value); + bnez(AT, slow_case); -+ fast_unlock(scr_reg, hdr_reg, tmp_reg, SCR1, slow_case); ++ lightweight_unlock(scr_reg, hdr_reg, tmp_reg, SCR1, slow_case); + b(count); + bind(slow_case); + } else if (LockingMode == LM_LEGACY) { @@ -24985,7 +25297,7 @@ index 00000000000..07be00ace59 + } + + // Record the receiver type. -+ record_klass_in_profile(receiver, mdp, reg2, true); ++ record_klass_in_profile(receiver, mdp, reg2); + bind(skip_receiver_profile); + + // The method data pointer needs to be updated to reflect the new target. @@ -25010,36 +25322,18 @@ index 00000000000..07be00ace59 +void InterpreterMacroAssembler::record_klass_in_profile_helper( + Register receiver, Register mdp, + Register reg2, int start_row, -+ Label& done, bool is_virtual_call) { ++ Label& done) { + if (TypeProfileWidth == 0) { -+ if (is_virtual_call) { -+ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); -+ } -+#if INCLUDE_JVMCI -+ else if (EnableJVMCI) { -+ increment_mdp_data_at(mdp, in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset())); -+ } -+#endif // INCLUDE_JVMCI ++ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); + } else { -+ int non_profiled_offset = -1; -+ if (is_virtual_call) { -+ non_profiled_offset = in_bytes(CounterData::count_offset()); -+ } -+#if INCLUDE_JVMCI -+ else if (EnableJVMCI) { -+ non_profiled_offset = in_bytes(ReceiverTypeData::nonprofiled_receiver_count_offset()); -+ } -+#endif // INCLUDE_JVMCI -+ + record_item_in_profile_helper(receiver, mdp, reg2, 0, done, TypeProfileWidth, -+ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset, non_profiled_offset); ++ &VirtualCallData::receiver_offset, &VirtualCallData::receiver_count_offset); + } +} + +void InterpreterMacroAssembler::record_item_in_profile_helper(Register item, Register mdp, + Register reg2, int start_row, Label& done, int total_rows, -+ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn, -+ int non_profiled_offset) { ++ OffsetFunction item_offset_fn, OffsetFunction item_count_offset_fn) { + int last_row = total_rows - 1; + assert(start_row <= last_row, "must be work left to do"); + // Test this row for both the item and for null. @@ -25070,16 +25364,12 @@ index 00000000000..07be00ace59 + // Failed the equality check on item[n]... Test for null. + if (start_row == last_row) { + // The only thing left to do is handle the null case. -+ if (non_profiled_offset >= 0) { -+ beqz(reg2, found_null); -+ // Item did not match any saved item and there is no empty row for it. -+ // Increment total counter to indicate polymorphic case. -+ increment_mdp_data_at(mdp, non_profiled_offset); -+ b(done); -+ bind(found_null); -+ } else { -+ bnez(reg2, done); -+ } ++ beqz(reg2, found_null); ++ // Item did not match any saved item and there is no empty row for it. ++ // Increment total counter to indicate polymorphic case. ++ increment_mdp_data_at(mdp, in_bytes(CounterData::count_offset())); ++ b(done); ++ bind(found_null); + break; + } + // Since null is rare, make it be the branch-taken case. @@ -25087,7 +25377,7 @@ index 00000000000..07be00ace59 + + // Put all the "Case 3" tests here. + record_item_in_profile_helper(item, mdp, reg2, start_row + 1, done, total_rows, -+ item_offset_fn, item_count_offset_fn, non_profiled_offset); ++ item_offset_fn, item_count_offset_fn); + + // Found a null. Keep searching for a matching item, + // but remember that this is an empty (unused) slot. @@ -25134,12 +25424,11 @@ index 00000000000..07be00ace59 +// done: + +void InterpreterMacroAssembler::record_klass_in_profile(Register receiver, -+ Register mdp, Register reg2, -+ bool is_virtual_call) { ++ Register mdp, Register reg2) { + assert(ProfileInterpreter, "must be profiling"); + Label done; + -+ record_klass_in_profile_helper(receiver, mdp, reg2, 0, done, is_virtual_call); ++ record_klass_in_profile_helper(receiver, mdp, reg2, 0, done); + + bind (done); +} @@ -25202,26 +25491,6 @@ index 00000000000..07be00ace59 + } +} + -+ -+void InterpreterMacroAssembler::profile_typecheck_failed(Register mdp) { -+ if (ProfileInterpreter && TypeProfileCasts) { -+ Label profile_continue; -+ -+ // If no method data exists, go to profile_continue. -+ test_method_data_pointer(mdp, profile_continue); -+ -+ int count_offset = in_bytes(CounterData::count_offset()); -+ // Back up the address, since we have already bumped the mdp. -+ count_offset -= in_bytes(VirtualCallData::virtual_call_data_size()); -+ -+ // *Decrement* the counter. We expect to see zero or small negatives. -+ increment_mdp_data_at(mdp, count_offset, true); -+ -+ bind (profile_continue); -+ } -+} -+ -+ +void InterpreterMacroAssembler::profile_typecheck(Register mdp, Register klass, Register reg2) { + if (ProfileInterpreter) { + Label profile_continue; @@ -25235,7 +25504,7 @@ index 00000000000..07be00ace59 + mdp_delta = in_bytes(VirtualCallData::virtual_call_data_size()); + + // Record the object type. -+ record_klass_in_profile(klass, mdp, reg2, false); ++ record_klass_in_profile(klass, mdp, reg2); + } + update_mdp_by_constant(mdp, mdp_delta); + @@ -25335,6 +25604,7 @@ index 00000000000..07be00ace59 + + +void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& mdo_addr) { ++ assert_different_registers(obj, AT, T5, mdo_addr.base(), mdo_addr.index()); + Label update, next, none; + + verify_oop(obj); @@ -25373,25 +25643,21 @@ index 00000000000..07be00ace59 + xorr(obj, obj, AT); + + assert(TypeEntries::type_klass_mask == -4, "must be"); -+ bstrpick_d(AT, obj, 63, 2); -+ beqz(AT, next); ++ bstrpick_d(T5, obj, 63, 2); ++ beqz(T5, next); + -+ andi(AT, obj, TypeEntries::type_unknown); -+ bnez(AT, next); ++ andi(T5, obj, TypeEntries::type_unknown); ++ bnez(T5, next); + -+ if (mdo_addr.index() == noreg) { -+ ld_d(AT, mdo_addr); -+ } else { -+ ld_d(AT, T0, mdo_addr.disp()); -+ } + beqz(AT, none); + -+ addi_d(AT, AT, -(TypeEntries::null_seen)); -+ beqz(AT, none); ++ addi_d(T5, AT, -(TypeEntries::null_seen)); ++ beqz(T5, none); + -+ // There is a chance that the checks above (re-reading profiling -+ // data from memory) fail if another thread has just set the ++ // There is a chance that the checks above ++ // fail if another thread has just set the + // profiling to this obj's klass ++ xorr(obj, obj, AT); // get back original value before XOR + if (mdo_addr.index() == noreg) { + ld_d(AT, mdo_addr); + } else { @@ -25423,6 +25689,11 @@ index 00000000000..07be00ace59 + } else { + st_d(obj, T0, mdo_addr.disp()); + } ++#ifdef ASSERT ++ assert(TypeEntries::type_mask == -2, "must be"); ++ bstrpick_d(obj, obj, 63, 1); ++ verify_klass_ptr(obj); ++#endif + + bind(next); + if (mdo_addr.index() != noreg) { @@ -26055,7 +26326,7 @@ index 00000000000..46e634599e7 +JRT_END diff --git a/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp b/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp new file mode 100644 -index 00000000000..b912250dce2 +index 00000000000..79a65cd5be1 --- /dev/null +++ b/src/hotspot/cpu/loongarch/javaFrameAnchor_loongarch.hpp @@ -0,0 +1,86 @@ @@ -26130,7 +26401,7 @@ index 00000000000..b912250dce2 + + intptr_t* last_Java_sp(void) const { return _last_Java_sp; } + -+ const address last_Java_pc(void) { return _last_Java_pc; } ++ address last_Java_pc(void) { return _last_Java_pc; } + +private: + @@ -26481,13 +26752,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..1a983e338a4 +index 00000000000..8679369b78f --- /dev/null +++ b/src/hotspot/cpu/loongarch/jvmciCodeInstaller_loongarch.cpp -@@ -0,0 +1,194 @@ +@@ -0,0 +1,195 @@ +/* + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 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 @@ -26516,6 +26787,7 @@ index 00000000000..1a983e338a4 +#include "jvmci/jvmciRuntime.hpp" +#include "jvmci/jvmciCompilerToVM.hpp" +#include "jvmci/jvmciJavaClasses.hpp" ++#include "oops/compressedKlass.hpp" +#include "oops/oop.inline.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.hpp" @@ -26712,10 +26984,10 @@ 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..e48d7a6a063 +index 00000000000..c725468b09f --- /dev/null +++ b/src/hotspot/cpu/loongarch/loongarch_64.ad -@@ -0,0 +1,15888 @@ +@@ -0,0 +1,15964 @@ +// +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -27690,7 +27962,7 @@ index 00000000000..e48d7a6a063 +} + + -+const bool Matcher::match_rule_supported(int opcode) { ++bool Matcher::match_rule_supported(int opcode) { + if (!has_match_rule(opcode)) + return false; + @@ -27699,11 +27971,19 @@ index 00000000000..e48d7a6a063 + case Op_ConvF2HF: + case Op_ConvHF2F: + case Op_StrInflatedCopy: ++ case Op_StrCompressedCopy: ++ case Op_EncodeISOArray: + if (!UseLSX) + return false; + case Op_PopCountI: + case Op_PopCountL: + return UsePopCountInstruction; ++ case Op_FmaF: ++ case Op_FmaD: ++ case Op_FmaVF: ++ case Op_FmaVD: ++ if (!UseFMA) ++ return false; + case Op_CompareAndSwapB: + case Op_CompareAndSwapS: + case Op_CompareAndExchangeB: @@ -27725,11 +28005,11 @@ index 00000000000..e48d7a6a063 + return true; // Per default match rules are supported. +} + -+const bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) { ++bool Matcher::match_rule_supported_superword(int opcode, int vlen, BasicType bt) { + return match_rule_supported_vector(opcode, vlen, bt); +} + -+const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { ++bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { + if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) + return false; + @@ -27750,6 +28030,9 @@ index 00000000000..e48d7a6a063 + if (vlen < 4 || !UseLASX) + return false; + break; ++ case Op_VectorUCastB2X: ++ case Op_VectorUCastS2X: ++ case Op_VectorUCastI2X: + case Op_VectorCastB2X: + case Op_VectorCastS2X: + case Op_VectorCastI2X: @@ -27772,12 +28055,12 @@ index 00000000000..e48d7a6a063 + return true; +} + -+const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { ++bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { + return false; +} + +// Vector calling convention not yet implemented. -+const bool Matcher::supports_vector_calling_convention(void) { ++bool Matcher::supports_vector_calling_convention(void) { + return false; +} + @@ -27838,7 +28121,7 @@ index 00000000000..e48d7a6a063 + return opnd->opcode() == VREG; +} + -+const bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) { ++bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) { + return false; +} + @@ -27850,16 +28133,16 @@ index 00000000000..e48d7a6a063 + return nullptr; +} + -+const int Matcher::scalable_vector_reg_size(const BasicType bt) { ++int Matcher::scalable_vector_reg_size(const BasicType bt) { + return -1; +} + -+const int Matcher::superword_max_vector_size(const BasicType bt) { ++int Matcher::superword_max_vector_size(const BasicType bt) { + return Matcher::max_vector_size(bt); +} + +// Vector ideal reg -+const uint Matcher::vector_ideal_reg(int size) { ++uint Matcher::vector_ideal_reg(int size) { + switch(size) { + case 4: return Op_VecS; + case 8: return Op_VecD; @@ -27887,7 +28170,7 @@ index 00000000000..e48d7a6a063 +} + +// Max vector size in bytes. 0 if not supported. -+const int Matcher::vector_width_in_bytes(BasicType bt) { ++int Matcher::vector_width_in_bytes(BasicType bt) { + int size = (int)MaxVectorSize; + if (size < 2*type2aelembytes(bt)) size = 0; + // But never < 4 @@ -27896,12 +28179,12 @@ index 00000000000..e48d7a6a063 +} + +// Limits on vector size (number of elements) loaded into vector. -+const int Matcher::max_vector_size(const BasicType bt) { ++int Matcher::max_vector_size(const BasicType bt) { + assert(is_java_primitive(bt), "only primitive type vectors"); + return vector_width_in_bytes(bt)/type2aelembytes(bt); +} + -+const int Matcher::min_vector_size(const BasicType bt) { ++int Matcher::min_vector_size(const BasicType bt) { + int max_size = max_vector_size(bt); + int size = 0; + @@ -28418,7 +28701,7 @@ index 00000000000..e48d7a6a063 + __ st_d(as_Register(Matcher::_regEncode[src_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { -+ st->print("\tst_d %s, [SP + #%d] # spill 8", ++ st->print("\tst_d %s, [SP + #%d]\t# spill 8", + Matcher::regName[src_first], + offset); +#endif @@ -28468,8 +28751,7 @@ index 00000000000..e48d7a6a063 + __ add_d(as_Register(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first]), R0); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("move(32-bit) %s <-- %s\t# spill 11", ++ st->print("\tmove(32-bit) %s <-- %s\t# spill 11", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28486,8 +28768,7 @@ index 00000000000..e48d7a6a063 + __ movgr2fr_d(as_FloatRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("movgr2fr_d %s, %s\t# spill 12", ++ st->print("\tmovgr2fr_d %s, %s\t# spill 12", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28501,8 +28782,7 @@ index 00000000000..e48d7a6a063 + __ movgr2fr_w(as_FloatRegister(Matcher::_regEncode[dst_first]), as_Register(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("movgr2fr_w %s, %s\t# spill 13", ++ st->print("\tmovgr2fr_w %s, %s\t# spill 13", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28523,8 +28803,7 @@ index 00000000000..e48d7a6a063 + __ fst_d( as_FloatRegister(Matcher::_regEncode[src_first]), Address(SP, offset) ); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("fst_d %s, [SP + #%d]\t# spill 14", ++ st->print("\tfst_d %s, [SP + #%d]\t# spill 14", + Matcher::regName[src_first], + offset); +#endif @@ -28539,8 +28818,7 @@ index 00000000000..e48d7a6a063 + __ fst_s(as_FloatRegister(Matcher::_regEncode[src_first]), Address(SP, offset)); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("fst_s %s, [SP + #%d]\t# spill 15", ++ st->print("\tfst_s %s, [SP + #%d]\t# spill 15", + Matcher::regName[src_first], + offset); +#endif @@ -28557,8 +28835,7 @@ index 00000000000..e48d7a6a063 + __ movfr2gr_d( as_Register(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("movfr2gr_d %s, %s\t# spill 16", ++ st->print("\tmovfr2gr_d %s, %s\t# spill 16", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28572,8 +28849,7 @@ index 00000000000..e48d7a6a063 + __ movfr2gr_s( as_Register(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("movfr2gr_s %s, %s\t# spill 17", ++ st->print("\tmovfr2gr_s %s, %s\t# spill 17", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28590,8 +28866,7 @@ index 00000000000..e48d7a6a063 + __ fmov_d( as_FloatRegister(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("fmov_d %s <-- %s\t# spill 18", ++ st->print("\tfmov_d %s <-- %s\t# spill 18", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -28605,8 +28880,7 @@ index 00000000000..e48d7a6a063 + __ fmov_s( as_FloatRegister(Matcher::_regEncode[dst_first]), as_FloatRegister(Matcher::_regEncode[src_first])); +#ifndef PRODUCT + } else { -+ st->print("\n\t"); -+ st->print("fmov_s %s <-- %s\t# spill 19", ++ st->print("\tfmov_s %s <-- %s\t# spill 19", + Matcher::regName[dst_first], + Matcher::regName[src_first]); +#endif @@ -29153,6 +29427,11 @@ index 00000000000..e48d7a6a063 + ciEnv::current()->record_failure("CodeCache is full"); + return; + } ++ } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) { ++ // The NOP here is purely to ensure that eliding a call to ++ // JVM_EnsureMaterializedForStackWalk doesn't change the code size. ++ __ nop(); ++ __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); + } else { + int method_index = resolved_method_index(cbuf); + RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) @@ -31063,7 +31342,8 @@ index 00000000000..e48d7a6a063 +opclass memory_exclusive(indOffset16, indirect); + +opclass mRegLorI2L(mRegI2L, mRegL); -+opclass mRegIorL2I( mRegI, mRegL2I); ++opclass mRegIorL2I(mRegI, mRegL2I); ++opclass mRegLorP(mRegL, mRegP); + +//----------PIPELINE----------------------------------------------------------- +// Rules which define the behavior of the target architectures pipeline. @@ -35005,6 +35285,26 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++instruct cmovD_cmpF_reg_reg(regD dst, regD src, regF tmp1, regF tmp2, cmpOp cop ) %{ ++ match(Set dst (CMoveD (Binary cop (CmpF tmp1 tmp2)) (Binary dst src))); ++ ins_cost(200); ++ format %{ ++ "CMP$cop $tmp1, $tmp2\t @cmovD_cmpF_reg_reg\n" ++ "\tCMOV $dst,$src \t @cmovD_cmpF_reg_reg" ++ %} ++ ins_encode %{ ++ FloatRegister reg_op1 = as_FloatRegister($tmp1$$reg); ++ FloatRegister reg_op2 = as_FloatRegister($tmp2$$reg); ++ FloatRegister dst = as_FloatRegister($dst$$reg); ++ FloatRegister src = as_FloatRegister($src$$reg); ++ int flag = $cop$$cmpcode; ++ ++ __ cmp_cmov(reg_op1, reg_op2, dst, src, (MacroAssembler::CMCompare) flag, true /* is_float */); ++ %} ++ ++ ins_pipe( pipe_slow ); ++%} ++ +instruct cmovF_cmpI_reg_reg(regF dst, regF src, mRegI tmp1, mRegI tmp2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpI tmp1 tmp2)) (Binary dst src))); + ins_cost(200); @@ -35026,6 +35326,27 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++instruct cmovF_cmpL_reg_reg(regF dst, regF src, mRegL tmp1, mRegL tmp2, cmpOp cop) %{ ++ match(Set dst (CMoveF (Binary cop (CmpL tmp1 tmp2)) (Binary dst src))); ++ ins_cost(200); ++ format %{ ++ "CMP$cop $tmp1, $tmp2\t @cmovF_cmpL_reg_reg\n" ++ "\tCMOV $dst, $src \t @cmovF_cmpL_reg_reg" ++ %} ++ ++ ins_encode %{ ++ Register op1 = $tmp1$$Register; ++ Register op2 = $tmp2$$Register; ++ FloatRegister dst = as_FloatRegister($dst$$reg); ++ FloatRegister src = as_FloatRegister($src$$reg); ++ int flag = $cop$$cmpcode; ++ ++ __ cmp_cmov(op1, op2, dst, src, (MacroAssembler::CMCompare) flag); ++ %} ++ ++ ins_pipe( pipe_slow ); ++%} ++ +instruct cmovD_cmpN_reg_reg(regD dst, regD src, mRegN tmp1, mRegN tmp2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpN tmp1 tmp2)) (Binary dst src))); + ins_cost(200); @@ -35068,12 +35389,13 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + -+instruct cmovD_cmpP_reg_reg(regD dst, regD src, mRegP tmp1, mRegP tmp2, cmpOp cop) %{ ++instruct cmovD_cmpLorP_reg_reg(regD dst, regD src, mRegLorP tmp1, mRegLorP tmp2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpP tmp1 tmp2)) (Binary dst src))); ++ match(Set dst (CMoveD (Binary cop (CmpL tmp1 tmp2)) (Binary dst src))); + ins_cost(200); + format %{ -+ "CMP$cop $tmp1, $tmp2\t @cmovD_cmpP_reg_reg\n" -+ "\tCMOV $dst, $src \t @cmovD_cmpP_reg_reg" ++ "CMP$cop $tmp1, $tmp2\t @cmovD_cmpLorP_reg_reg\n" ++ "\tCMOV $dst, $src \t @cmovD_cmpLorP_reg_reg" + %} + + ins_encode %{ @@ -35135,6 +35457,26 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++instruct cmovF_cmpD_reg_reg(regF dst, regF src, regD tmp1, regD tmp2, cmpOp cop ) %{ ++ match(Set dst (CMoveF (Binary cop (CmpD tmp1 tmp2)) (Binary dst src))); ++ ins_cost(200); ++ format %{ ++ "CMP$cop $tmp1, $tmp2\t @cmovF_cmpD_reg_reg\n" ++ "\tCMOV $dst,$src \t @cmovF_cmpD_reg_reg" ++ %} ++ ++ ins_encode %{ ++ FloatRegister reg_op1 = $tmp1$$FloatRegister; ++ FloatRegister reg_op2 = $tmp2$$FloatRegister; ++ FloatRegister dst = $dst$$FloatRegister; ++ FloatRegister src = $src$$FloatRegister; ++ int flag = $cop$$cmpcode; ++ ++ __ cmp_cmov(reg_op1, reg_op2, dst, src, (MacroAssembler::CMCompare) flag, false /* is_float */); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +// Manifest a CmpL result in an integer register. Very painful. +// This is the test to avoid. +instruct cmpL3_reg_zero(mRegI dst, mRegL src1, immL_0 zero) %{ @@ -35280,275 +35622,80 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + -+instruct clear_array(t8RegL cnt, t3_RegP base, Universe dummy, mRegI tmp) %{ ++instruct clear_array(a2RegL cnt, a0_RegP base, Universe dummy, a1RegL value) %{ + match(Set dummy (ClearArray cnt base)); -+ effect(USE_KILL base, TEMP tmp); -+ format %{ "CLEAR_ARRAY base = $base, cnt = $cnt # Clear doublewords" %} -+ ins_encode %{ -+ // Assume cnt is the number of bytes in an array to be cleared, -+ // and base points to the starting address of the array. -+ Register base = $base$$Register; -+ Register cnt = $cnt$$Register; -+ Register end = SCR1; -+ Register tmp = $tmp$$Register; -+ FloatRegister zero = fscratch; -+ Label inthead, intloop, done; -+ Label loop, lt16, lt32; -+ -+ __ alsl_d(end, cnt, base, 3 - 1); -+ -+ if (UseLASX && false) { -+ __ li(tmp, 16); -+ __ bltu(cnt, tmp, inthead); -+ -+ __ xvxor_v(zero, zero, zero); -+ __ st_d(R0, base, 0); -+ __ st_d(R0, base, 8); -+ __ st_d(R0, base, 16); -+ __ st_d(R0, base, 24); -+ -+ __ bstrins_d(base, R0, 4, 0); -+ __ addi_d(base, base, 32); -+ __ addi_d(tmp, end, -64); -+ -+ __ bind(loop); -+ __ xvst(zero, base, 0); -+ __ xvst(zero, base, 32); -+ __ addi_d(base, base, 64); -+ __ bltu(base, tmp, loop); -+ -+ __ addi_d(tmp, end, -32); -+ __ bgeu(base, tmp, lt32); -+ __ xvst(zero, base, 0); -+ -+ __ bind(lt32); -+ __ st_d(R0, end, -32); -+ __ st_d(R0, end, -24); -+ __ st_d(R0, end, -16); -+ __ st_d(R0, end, -8); -+ __ b(done); -+ } else if (UseLSX) { -+ __ li(tmp, 8); -+ __ bltu(cnt, tmp, inthead); -+ -+ __ vxor_v(zero, zero, zero); -+ __ st_d(R0, base, 0); -+ __ st_d(R0, base, 8); -+ -+ __ bstrins_d(base, R0, 3, 0); -+ __ addi_d(base, base, 16); -+ __ addi_d(tmp, end, -32); ++ effect(TEMP value, USE_KILL cnt, USE_KILL base); + -+ __ bind(loop); -+ __ vst(zero, base, 0); -+ __ vst(zero, base, 16); -+ __ addi_d(base, base, 32); -+ __ bltu(base, tmp, loop); -+ -+ __ addi_d(tmp, end, -16); -+ __ bgeu(base, tmp, lt16); -+ __ vst(zero, base, 0); -+ -+ __ bind(lt16); -+ __ st_d(R0, end, -16); -+ __ st_d(R0, end, -8); -+ __ b(done); -+ } -+ -+ __ bind(inthead); -+ __ beqz(cnt, done); -+ __ bind(intloop); -+ __ st_d(R0, base, 0); -+ __ addi_d(base, base, 8); -+ __ blt(base, end, intloop); -+ __ bind(done); -+ %} -+ ins_pipe( pipe_slow ); -+%} -+ -+instruct clear_array_imm(immL cnt, t3_RegP base, Universe dummy) %{ -+ match(Set dummy (ClearArray cnt base)); -+ effect(USE_KILL base); -+ format %{ "CLEAR_ARRAY base = $base, cnt = $cnt # Clear doublewords" %} ++ format %{ "CLEAR_ARRAY base = $base, cnt = $cnt @ clear_array" %} + ins_encode %{ + // Assume cnt is the number of bytes in an array to be cleared, + // and base points to the starting address of the array. -+ Register base = $base$$Register; -+ long cnt = $cnt$$constant; -+ Label loop; -+ -+ int tmp = cnt % 8; -+ int i = 0; -+ for (; i < tmp; i++) { -+ __ st_d(R0, base, i * 8); -+ } -+ if (cnt - tmp) { -+ __ li(AT, cnt); -+ __ alsl_d(AT, AT, base, 2); -+ __ addi_d(base, base, i * 8); -+ __ bind(loop); -+ __ st_d(R0, base, 0); -+ __ st_d(R0, base, 8); -+ __ st_d(R0, base, 16); -+ __ st_d(R0, base, 24); -+ __ st_d(R0, base, 32); -+ __ st_d(R0, base, 40); -+ __ st_d(R0, base, 48); -+ __ st_d(R0, base, 56); -+ __ addi_d(base, base, 64); -+ __ blt(base, AT, loop); -+ } ++ __ move($value$$Register, R0); ++ __ trampoline_call(RuntimeAddress(StubRoutines::la::arrayof_jlong_fill())); + %} -+ ins_pipe( pipe_slow ); -+%} -+ -+instruct clear_array_imm_lsx(immL_gt_7 cnt, t3_RegP base, Universe dummy, mRegI tmp) %{ -+ predicate(UseLSX); -+ match(Set dummy (ClearArray cnt base)); -+ effect(USE_KILL base, TEMP tmp); -+ ins_cost(80); -+ format %{ "CLEAR_ARRAY base = $base, cnt = $cnt # Clear doublewords by LSX" %} -+ ins_encode %{ -+ // Assume cnt is the number of bytes in an array to be cleared, -+ // and base points to the starting address of the array. -+ Register base = $base$$Register; -+ Register end = SCR1; -+ Register tmp = $tmp$$Register; -+ FloatRegister zero = fscratch; -+ long cnt = $cnt$$constant; -+ Label loop, lt16; -+ -+ __ vxor_v(zero, zero, zero); -+ -+ __ li(tmp, cnt); -+ __ alsl_d(end, tmp, base, 3 - 1); -+ __ st_d(R0, base, 0); -+ __ st_d(R0, base, 8); + -+ __ bstrins_d(base, R0, 3, 0); -+ __ addi_d(base, base, 16); -+ __ addi_d(tmp, end, -32); -+ -+ __ bind(loop); -+ __ vst(zero, base, 0); -+ __ vst(zero, base, 16); -+ __ addi_d(base, base, 32); -+ __ bltu(base, tmp, loop); -+ -+ __ addi_d(tmp, end, -16); -+ __ bgeu(base, tmp, lt16); -+ __ vst(zero, base, 0); -+ -+ __ bind(lt16); -+ __ st_d(R0, end, -16); -+ __ st_d(R0, end, -8); -+ %} + ins_pipe( pipe_slow ); +%} + -+instruct clear_array_imm_lasx(immL_gt_15 cnt, t3_RegP base, Universe dummy, mRegI tmp) %{ -+ predicate(UseLASX && false); -+ match(Set dummy (ClearArray cnt base)); -+ effect(USE_KILL base, TEMP tmp); -+ ins_cost(60); -+ format %{ "CLEAR_ARRAY base = $base, cnt = $cnt # Clear doublewords by LASX" %} -+ ins_encode %{ -+ // Assume cnt is the number of bytes in an array to be cleared, -+ // and base points to the starting address of the array. -+ Register base = $base$$Register; -+ Register end = SCR1; -+ Register tmp = $tmp$$Register; -+ FloatRegister zero = fscratch; -+ long cnt = $cnt$$constant; -+ Label loop, lt32; -+ -+ __ xvxor_v(zero, zero, zero); -+ -+ __ li(tmp, cnt); -+ __ alsl_d(end, tmp, base, 3 - 1); -+ __ st_d(R0, base, 0); -+ __ st_d(R0, base, 8); -+ __ st_d(R0, base, 16); -+ __ st_d(R0, base, 24); -+ -+ __ bstrins_d(base, R0, 4, 0); -+ __ addi_d(base, base, 32); -+ __ addi_d(tmp, end, -64); -+ -+ __ bind(loop); -+ __ xvst(zero, base, 0); -+ __ xvst(zero, base, 32); -+ __ addi_d(base, base, 64); -+ __ bltu(base, tmp, loop); -+ -+ __ addi_d(tmp, end, -32); -+ __ bgeu(base, tmp, lt32); -+ __ xvst(zero, base, 0); -+ -+ __ bind(lt32); -+ __ st_d(R0, end, -32); -+ __ st_d(R0, end, -24); -+ __ st_d(R0, end, -16); -+ __ st_d(R0, end, -8); -+ %} -+ ins_pipe( pipe_slow ); -+%} -+ -+instruct string_compareL(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI result, mRegL tmp1, mRegL tmp2) %{ ++instruct string_compareL(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI 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(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP tmp1,TEMP tmp2, TEMP_DEF result); ++ 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 -> $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); ++ StrIntrinsicNode::LL, $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) %{ ++instruct string_compareU(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI 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(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP tmp1, TEMP tmp2, TEMP_DEF result); ++ 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 char[] $str1[len: $cnt1], $str2[len: $cnt2] tmp1:$tmp1, tmp2:$tmp2 -> $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); ++ StrIntrinsicNode::UU, $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) %{ ++instruct string_compareLU(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI 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(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP tmp1, TEMP tmp2, TEMP_DEF result); ++ 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 -> $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); ++ StrIntrinsicNode::LU, $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) %{ ++instruct string_compareUL(a4_RegP str1, mA5RegI cnt1, a6_RegP str2, mA7RegI cnt2, mRegI 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(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, TEMP tmp1, TEMP tmp2, TEMP_DEF result); ++ 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 -> $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); ++ StrIntrinsicNode::UL, $tmp1$$Register, $tmp2$$Register, ++ $vtmp1$$FloatRegister, $vtmp2$$FloatRegister); + %} + + ins_pipe( pipe_slow ); @@ -35686,62 +35833,59 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + -+instruct count_positives(a4_RegP src, mA5RegI len, mRegI result, mRegL tmp1) %{ ++instruct count_positives(mRegP src, mRegI len, mRegI result, ++ mRegL tmp1, mRegL tmp2) %{ + match(Set result (CountPositives src len)); -+ effect(USE src, USE len, TEMP_DEF result, TEMP tmp1); -+ format %{ "count positives byte[] src:$src, len:$len -> $result TEMP($tmp1) @ count_positives" %} -+ ins_cost(200); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2); + -+ ins_encode %{ -+ __ count_positives($src$$Register, $len$$Register, $result$$Register, $tmp1$$Register); -+ %} -+ -+ ins_pipe( pipe_slow ); -+%} -+ -+instruct count_positives_v(a4_RegP src, mA5RegI len, mRegI result, mRegL tmp1) %{ -+ predicate(UseLSX); -+ match(Set result (CountPositives src len)); -+ effect(USE src, USE len, TEMP_DEF result, TEMP tmp1); -+ format %{ "vectorized count positives byte[] src:$src, len:$len -> $result TEMP($tmp1) @ count_positives_v" %} -+ ins_cost(150); ++ format %{ "count positives byte[] src:$src, len:$len -> $result TEMP($tmp1, $tmp2) @ count_positives" %} + + ins_encode %{ -+ __ count_positives_v($src$$Register, $len$$Register, $result$$Register, $tmp1$$Register); ++ __ count_positives($src$$Register, $len$$Register, $result$$Register, ++ $tmp1$$Register, $tmp2$$Register); + %} + + ins_pipe( pipe_slow ); +%} + +// fast char[] to byte[] compression -+instruct string_compress(a4_RegP src, a5_RegP dst, mA6RegI len, mRegI result, -+ mRegL tmp1, mRegL tmp2, mRegL tmp3) ++instruct string_compress(a2_RegP src, mRegP dst, mRegI len, mRegI result, ++ mRegL tmp1, mRegL tmp2, mRegL tmp3, ++ regF vtemp1, regF vtemp2, regF vtemp3, regF vtemp4) +%{ ++ predicate(UseLSX); + match(Set result (StrCompressedCopy src (Binary dst len))); -+ effect(USE_KILL src, USE_KILL dst, USE_KILL len, TEMP_DEF result, -+ TEMP tmp1, TEMP tmp2, TEMP tmp3); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, ++ TEMP vtemp1, TEMP vtemp2, TEMP vtemp3, TEMP vtemp4, USE_KILL src); + + format %{ "String Compress $src,$dst -> $result @ string_compress " %} ++ + ins_encode %{ + __ char_array_compress($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp1$$Register, -+ $tmp2$$Register, $tmp3$$Register); ++ $tmp2$$Register, $tmp3$$Register, ++ $vtemp1$$FloatRegister, $vtemp2$$FloatRegister, ++ $vtemp3$$FloatRegister, $vtemp4$$FloatRegister); + %} ++ + ins_pipe( pipe_slow ); +%} + +// byte[] to char[] inflation +instruct string_inflate(Universe dummy, a4_RegP src, a5_RegP dst, mA6RegI len, -+ regF vtemp1, regF vtemp2) ++ mRegL tmp1, mRegL tmp2, regF vtemp1, regF vtemp2) +%{ + predicate(UseLSX); + match(Set dummy (StrInflatedCopy src (Binary dst len))); -+ effect(USE_KILL src, USE_KILL dst, USE_KILL len, TEMP vtemp1, TEMP vtemp2); ++ effect(TEMP tmp1, TEMP tmp2, TEMP vtemp1, TEMP vtemp2, ++ USE_KILL src, USE_KILL dst, USE_KILL len); + -+ format %{ "String Inflate $src,$dst @ string_inflate " %} ++ format %{ "String Inflate $src, $dst, len:$len " ++ "TEMP($tmp1, $tmp2, $vtemp1, $vtemp2) @ string_inflate " %} + + ins_encode %{ + __ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register, ++ $tmp1$$Register, $tmp2$$Register, + $vtemp1$$FloatRegister, $vtemp2$$FloatRegister); + %} + @@ -35794,38 +35938,46 @@ index 00000000000..e48d7a6a063 +%} + +// encode char[] to byte[] in ISO_8859_1 -+instruct encode_iso_array(a4_RegP src, a5_RegP dst, mA6RegI len, mRegI result, -+ mRegL tmp1, mRegL tmp2, mRegL tmp3) ++instruct encode_iso_array(a2_RegP src, mRegP dst, mRegI len, mRegI result, ++ mRegL tmp1, mRegL tmp2, mRegL tmp3, ++ regF vtemp1, regF vtemp2, regF vtemp3, regF vtemp4) +%{ -+ predicate(!((EncodeISOArrayNode*)n)->is_ascii()); ++ predicate(UseLSX && !((EncodeISOArrayNode*)n)->is_ascii()); + match(Set result (EncodeISOArray src (Binary dst len))); -+ effect(USE_KILL src, USE_KILL dst, USE_KILL len, TEMP_DEF result, -+ TEMP tmp1, TEMP tmp2, TEMP tmp3); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, ++ TEMP vtemp1, TEMP vtemp2, TEMP vtemp3, TEMP vtemp4, USE_KILL src); + + format %{ "Encode ISO array $src,$dst,$len -> $result @ encode_iso_array" %} ++ + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp1$$Register, -+ $tmp2$$Register, $tmp3$$Register, false); ++ $tmp2$$Register, $tmp3$$Register, false, ++ $vtemp1$$FloatRegister, $vtemp2$$FloatRegister, ++ $vtemp3$$FloatRegister, $vtemp4$$FloatRegister); + %} + + ins_pipe( pipe_slow ); +%} + +// encode char[] to byte[] in ASCII -+instruct encode_ascii_array(a4_RegP src, a5_RegP dst, mA6RegI len, mRegI result, -+ mRegL tmp1, mRegL tmp2, mRegL tmp3) ++instruct encode_ascii_array(a2_RegP src, mRegP dst, mRegI len, mRegI result, ++ mRegL tmp1, mRegL tmp2, mRegL tmp3, ++ regF vtemp1, regF vtemp2, regF vtemp3, regF vtemp4) +%{ -+ predicate(((EncodeISOArrayNode*)n)->is_ascii()); ++ predicate(UseLSX && ((EncodeISOArrayNode*)n)->is_ascii()); + match(Set result (EncodeISOArray src (Binary dst len))); -+ effect(USE_KILL src, USE_KILL dst, USE_KILL len, TEMP_DEF result, -+ TEMP tmp1, TEMP tmp2, TEMP tmp3); ++ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, ++ TEMP vtemp1, TEMP vtemp2, TEMP vtemp3, TEMP vtemp4, USE_KILL src); + + format %{ "Encode ASCII array $src,$dst,$len -> $result @ encode_ascii_array" %} ++ + ins_encode %{ + __ encode_iso_array($src$$Register, $dst$$Register, $len$$Register, + $result$$Register, $tmp1$$Register, -+ $tmp2$$Register, $tmp3$$Register, true); ++ $tmp2$$Register, $tmp3$$Register, true, ++ $vtemp1$$FloatRegister, $vtemp2$$FloatRegister, ++ $vtemp3$$FloatRegister, $vtemp4$$FloatRegister); + %} + + ins_pipe( pipe_slow ); @@ -36524,125 +36676,101 @@ index 00000000000..e48d7a6a063 + +// src1 * src2 + src3 +instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ -+ predicate(UseFMA); + match(Set dst (FmaF src3 (Binary src1 src2))); -+ + format %{ "fmadd_s $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fmadd_s(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + +// src1 * src2 + src3 +instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ -+ predicate(UseFMA); + match(Set dst (FmaD src3 (Binary src1 src2))); -+ + format %{ "fmadd_d $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fmadd_d(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + +// src1 * src2 - src3 +instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3, immF_0 zero) %{ -+ predicate(UseFMA); + match(Set dst (FmaF (NegF src3) (Binary src1 src2))); -+ + format %{ "fmsub_s $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fmsub_s(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + +// src1 * src2 - src3 +instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3, immD_0 zero) %{ -+ predicate(UseFMA); + match(Set dst (FmaD (NegD src3) (Binary src1 src2))); -+ + format %{ "fmsub_d $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fmsub_d(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + -+// -src1 * src2 - src3 ++// src1 * (-src2) - src3 ++// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3" +instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3, immF_0 zero) %{ -+ predicate(UseFMA); -+ match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2))); + match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2)))); -+ + format %{ "fnmadds $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fnmadd_s(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + -+// -src1 * src2 - src3 ++// src1 * (-src2) - src3 ++// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3" +instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3, immD_0 zero) %{ -+ predicate(UseFMA); -+ match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2))); + match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2)))); -+ + format %{ "fnmaddd $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fnmadd_d(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + -+// -src1 * src2 + src3 ++// src1 * (-src2) + src3 ++// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3" +instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{ -+ predicate(UseFMA); -+ match(Set dst (FmaF src3 (Binary (NegF src1) src2))); + match(Set dst (FmaF src3 (Binary src1 (NegF src2)))); -+ + format %{ "fnmsubs $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fnmsub_s(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + -+// -src1 * src2 + src3 ++// src1 * (-src2) + src3 ++// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3" +instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{ -+ predicate(UseFMA); -+ match(Set dst (FmaD src3 (Binary (NegD src1) src2))); + match(Set dst (FmaD src3 (Binary src1 (NegD src2)))); -+ + format %{ "fnmsubd $dst, $src1, $src2, $src3" %} -+ + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + __ fnmsub_d(as_FloatRegister($dst$$reg), as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg), as_FloatRegister($src3$$reg)); + %} -+ + ins_pipe( fpu_arith3 ); +%} + @@ -37755,6 +37883,34 @@ index 00000000000..e48d7a6a063 + ins_pipe(pipe_slow); +%} + ++instruct round_float_reg(mRegI dst, regF src, regF vtemp1) ++%{ ++ match(Set dst (RoundF src)); ++ effect(TEMP_DEF dst, TEMP vtemp1); ++ format %{ "round_float $dst, $src\t# " ++ "TEMP($vtemp1) @round_float_reg" %} ++ ins_encode %{ ++ __ java_round_float($dst$$Register, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct round_double_reg(mRegL dst, regD src, regD vtemp1) ++%{ ++ match(Set dst (RoundD src)); ++ effect(TEMP_DEF dst, TEMP vtemp1); ++ format %{ "round_double $dst, $src\t# " ++ "TEMP($vtemp1) @round_double_reg" %} ++ ins_encode %{ ++ __ java_round_double($dst$$Register, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +instruct roundD(regD dst, regD src, immI rmode) %{ + predicate(UseLSX); + match(Set dst (RoundDoubleMode src rmode)); @@ -38671,7 +38827,6 @@ index 00000000000..e48d7a6a063 +%} + +instruct compareAndSwapL(mRegI res, memory_exclusive mem_ptr, mRegL oldval, mRegL newval) %{ -+ predicate(VM_Version::supports_cx8()); + match(Set res (CompareAndSwapL mem_ptr (Binary oldval newval))); + effect(TEMP_DEF res); + ins_cost(3 * MEMORY_REF_COST); @@ -39598,26 +39753,6 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_serial ); +%} + -+//----------Arithmetic Conversion Instructions--------------------------------- -+ -+instruct roundFloat_nop(regF dst) -+%{ -+ match(Set dst (RoundFloat dst)); -+ -+ ins_cost(0); -+ ins_encode(); -+ ins_pipe( empty ); -+%} -+ -+instruct roundDouble_nop(regD dst) -+%{ -+ match(Set dst (RoundDouble dst)); -+ -+ ins_cost(0); -+ ins_encode(); -+ ins_pipe( empty ); -+%} -+ +//----------BSWAP Instructions------------------------------------------------- +instruct bytes_reverse_int(mRegI dst, mRegIorL2I src) %{ + match(Set dst (ReverseBytesI src)); @@ -39813,9 +39948,7 @@ index 00000000000..e48d7a6a063 +// ------------------------------- Replicate ---------------------------------- + +instruct replV(vReg dst, mRegI src) %{ -+ match(Set dst (ReplicateB src)); -+ match(Set dst (ReplicateS src)); -+ match(Set dst (ReplicateI src)); ++ match(Set dst (Replicate src)); + format %{ "(x)vreplgr2vr $dst, $src\t# @replV" %} + ins_encode %{ + if (Matcher::vector_length_in_bytes(this) > 16) { @@ -39840,7 +39973,7 @@ index 00000000000..e48d7a6a063 +%} + +instruct replVL(vReg dst, mRegL src) %{ -+ match(Set dst (ReplicateL src)); ++ match(Set dst (Replicate src)); + format %{ "(x)vreplgr2vr.d $dst, $src\t# @replVL" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -39854,7 +39987,7 @@ index 00000000000..e48d7a6a063 +%} + +instruct replVF(vReg dst, regF src) %{ -+ match(Set dst (ReplicateF src)); ++ match(Set dst (Replicate src)); + format %{ "(x)vreplve0.w $dst, $src\t# @replVF" %} + ins_encode %{ + __ vreplvei_w($dst$$FloatRegister, $src$$FloatRegister, 0); @@ -39870,7 +40003,7 @@ index 00000000000..e48d7a6a063 +%} + +instruct replVD(vReg dst, regD src) %{ -+ match(Set dst (ReplicateD src)); ++ match(Set dst (Replicate src)); + format %{ "(x)vreplve0.d $dst, $src\t# @replVD" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -39884,7 +40017,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct replVB_imm(vReg dst, immI_M128_255 imm) %{ -+ match(Set dst (ReplicateB imm)); ++ predicate(Matcher::vector_element_basic_type(n) == T_BYTE); ++ match(Set dst (Replicate imm)); + format %{ "(x)vldi $dst, $imm\t# @replVB_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -39900,8 +40034,9 @@ index 00000000000..e48d7a6a063 +%} + +instruct replV_imm(vReg dst, immI10 imm) %{ -+ match(Set dst (ReplicateS imm)); -+ match(Set dst (ReplicateI imm)); ++ predicate(Matcher::vector_element_basic_type(n) == T_SHORT || ++ Matcher::vector_element_basic_type(n) == T_INT); ++ match(Set dst (Replicate imm)); + format %{ "(x)vldi $dst, $imm\t# @replV_imm" %} + ins_encode %{ + if (Matcher::vector_length_in_bytes(this) > 16) { @@ -39924,7 +40059,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct replVL_imm(vReg dst, immL10 imm) %{ -+ match(Set dst (ReplicateL imm)); ++ predicate(Matcher::vector_element_basic_type(n) == T_LONG); ++ match(Set dst (Replicate imm)); + format %{ "(x)vldi $dst, $imm\t# @replVL_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -39976,9 +40112,9 @@ index 00000000000..e48d7a6a063 +%} + +instruct addV_imm(vReg dst, vReg src, immIU5 imm) %{ -+ match(Set dst (AddVB src (ReplicateB imm))); -+ match(Set dst (AddVS src (ReplicateS imm))); -+ match(Set dst (AddVI src (ReplicateI imm))); ++ match(Set dst (AddVB src (Replicate imm))); ++ match(Set dst (AddVS src (Replicate imm))); ++ match(Set dst (AddVI src (Replicate imm))); + format %{ "(x)vaddi $dst, $src, $imm\t# @addV_imm" %} + ins_encode %{ + if (Matcher::vector_length_in_bytes(this) > 16) { @@ -40003,7 +40139,7 @@ index 00000000000..e48d7a6a063 +%} + +instruct addVL_imm(vReg dst, vReg src, immLU5 imm) %{ -+ match(Set dst (AddVL src (ReplicateL imm))); ++ match(Set dst (AddVL src (Replicate imm))); + format %{ "(x)vaddi.du $dst, $src, $imm\t# @addVL_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -40055,9 +40191,9 @@ index 00000000000..e48d7a6a063 +%} + +instruct subV_imm(vReg dst, vReg src, immIU5 imm) %{ -+ match(Set dst (SubVB src (ReplicateB imm))); -+ match(Set dst (SubVS src (ReplicateB imm))); -+ match(Set dst (SubVI src (ReplicateB imm))); ++ match(Set dst (SubVB src (Replicate imm))); ++ match(Set dst (SubVS src (Replicate imm))); ++ match(Set dst (SubVI src (Replicate imm))); + format %{ "(x)vsubi $dst, $src, $imm\t# @subV_imm" %} + ins_encode %{ + if (Matcher::vector_length_in_bytes(this) > 16) { @@ -40082,7 +40218,7 @@ index 00000000000..e48d7a6a063 +%} + +instruct subVL_imm(vReg dst, vReg src, immLU5 imm) %{ -+ match(Set dst (SubVL src (ReplicateL imm))); ++ match(Set dst (SubVL src (Replicate imm))); + format %{ "(x)vsubi.du $dst, $src, $imm\t# @subVL_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -40485,6 +40621,7 @@ index 00000000000..e48d7a6a063 + match(Set dst (FmaVD src3 (Binary src1 src2))); + format %{ "(x)vfmadd $dst, $src1, $src2, $src3\t# @fmaddV" %} + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + if (Matcher::vector_length_in_bytes(this) > 16) { + switch(Matcher::vector_element_basic_type(this)) { + case T_FLOAT : __ xvfmadd_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); break; @@ -40541,6 +40678,7 @@ index 00000000000..e48d7a6a063 + match(Set dst (FmaVF (NegVF src3) (Binary src1 src2))); + format %{ "(x)vfmsub $dst, $src1, $src2, $src3\t# @fmsubV" %} + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + if (Matcher::vector_length_in_bytes(this) > 16) { + switch(Matcher::vector_element_basic_type(this)) { + case T_FLOAT : __ xvfmsub_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); break; @@ -40562,14 +40700,14 @@ index 00000000000..e48d7a6a063 + +// --------------------------------- FNMADD ----------------------------------- + -+// -src1 * src2 - src3 ++// src1 * (-src2) - src3 ++// "(-src1) * src2 - src3" has been idealized to "src2 * (-src1) - src3" +instruct fnmaddV(vReg dst, vReg src1, vReg src2, vReg src3) %{ -+ match(Set dst (FmaVF (NegVF src3) (Binary (NegVF src1) src2))); + match(Set dst (FmaVF (NegVF src3) (Binary src1 (NegVF src2)))); -+ match(Set dst (FmaVD (NegVD src3) (Binary (NegVD src1) src2))); + match(Set dst (FmaVD (NegVD src3) (Binary src1 (NegVD src2)))); + format %{ "(x)vfnmadd $dst, $src1, $src2, $src3\t# @fnmaddV" %} + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + if (Matcher::vector_length_in_bytes(this) > 16) { + switch(Matcher::vector_element_basic_type(this)) { + case T_FLOAT : __ xvfnmadd_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); break; @@ -40591,14 +40729,14 @@ index 00000000000..e48d7a6a063 + +// --------------------------------- FNMSUB ----------------------------------- + -+// -src1 * src2 + src3 ++// src1 * (-src2) + src3 ++// "(-src1) * src2 + src3" has been idealized to "src2 * (-src1) + src3" +instruct fnmsubV(vReg dst, vReg src1, vReg src2, vReg src3) %{ -+ match(Set dst (FmaVF src3 (Binary (NegVF src1) src2))); + match(Set dst (FmaVF src3 (Binary src1 (NegVF src2)))); -+ match(Set dst (FmaVD src3 (Binary (NegVD src1) src2))); + match(Set dst (FmaVD src3 (Binary src1 (NegVD src2)))); + format %{ "(x)vfnmsub $dst, $src1, $src2, $src3\t# @fnmsubV" %} + ins_encode %{ ++ assert(UseFMA, "Needs FMA instructions support."); + if (Matcher::vector_length_in_bytes(this) > 16) { + switch(Matcher::vector_element_basic_type(this)) { + case T_FLOAT : __ xvfnmsub_s($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister); break; @@ -41086,7 +41224,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct andVB_imm(vReg dst, vReg src, immIU8 imm) %{ -+ match(Set dst (AndV src (ReplicateB imm))); ++ predicate(Matcher::vector_element_basic_type(n) == T_BYTE); ++ match(Set dst (AndV src (Replicate imm))); + format %{ "(x)vandi.b $dst, $src, $imm\t# @andVB_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -41120,7 +41259,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct orVB_imm(vReg dst, vReg src, immIU8 imm) %{ -+ match(Set dst (OrV src (ReplicateB imm))); ++ predicate(Matcher::vector_element_basic_type(n) == T_BYTE); ++ match(Set dst (OrV src (Replicate imm))); + format %{ "(x)vori.b $dst, $src, $imm\t# @orVB_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -41154,7 +41294,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct xor16B_imm(vReg dst, vReg src, immIU8 imm) %{ -+ match(Set dst (XorV src (ReplicateB imm))); ++ predicate(Matcher::vector_element_basic_type(n) == T_BYTE); ++ match(Set dst (XorV src (Replicate imm))); + format %{ "(x)vxori.b $dst, $src, $imm\t# @xor16B_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -41172,9 +41313,7 @@ index 00000000000..e48d7a6a063 +// --------------------------------- NOR -------------------------------------- + +instruct norV(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{ -+ match(Set dst (XorV (OrV src1 src2) (ReplicateB m1))); -+ match(Set dst (XorV (OrV src1 src2) (ReplicateS m1))); -+ match(Set dst (XorV (OrV src1 src2) (ReplicateI m1))); ++ match(Set dst (XorV (OrV src1 src2) (Replicate m1))); + format %{ "(x)vnor.v $dst, $src1, $src2\t# @norV" %} + ins_encode %{ + switch (Matcher::vector_length_in_bytes(this)) { @@ -41190,7 +41329,8 @@ index 00000000000..e48d7a6a063 +%} + +instruct norVB_imm(vReg dst, vReg src, immIU8 imm, immI_M1 m1) %{ -+ match(Set dst (XorV (OrV src (ReplicateB imm)) (ReplicateB m1))); ++ predicate(Matcher::vector_element_basic_type(n) == T_BYTE); ++ match(Set dst (XorV (OrV src (Replicate imm)) (Replicate m1))); + format %{ "(x)vnori.b $dst, $src, $imm\t# @norVB_imm" %} + ins_encode %{ + switch (Matcher::vector_length(this)) { @@ -41208,9 +41348,7 @@ index 00000000000..e48d7a6a063 +// --------------------------------- ANDN ------------------------------------- + +instruct andnV(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{ -+ match(Set dst (AndV src2 (XorV src1 (ReplicateB m1)))); -+ match(Set dst (AndV src2 (XorV src1 (ReplicateS m1)))); -+ match(Set dst (AndV src2 (XorV src1 (ReplicateI m1)))); ++ match(Set dst (AndV src2 (XorV src1 (Replicate m1)))); + format %{ "(x)vandn.v $dst, $src1, $src2\t# @andnV" %} + ins_encode %{ + switch (Matcher::vector_length_in_bytes(this)) { @@ -41228,9 +41366,7 @@ index 00000000000..e48d7a6a063 +// --------------------------------- ORN -------------------------------------- + +instruct ornV(vReg dst, vReg src1, vReg src2, immI_M1 m1) %{ -+ match(Set dst (OrV src1 (XorV src2 (ReplicateB m1)))); -+ match(Set dst (OrV src1 (XorV src2 (ReplicateS m1)))); -+ match(Set dst (OrV src1 (XorV src2 (ReplicateI m1)))); ++ match(Set dst (OrV src1 (XorV src2 (Replicate m1)))); + format %{ "(x)vorn.v $dst, $src1, $src2\t# @ornV" %} + ins_encode %{ + switch (Matcher::vector_length_in_bytes(this)) { @@ -41305,6 +41441,68 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++// ------------------------------ Vector Round --------------------------------- ++ ++instruct round_float_lsx(vReg dst, vReg src, vReg vtemp1, vReg vtemp2) %{ ++ predicate(Matcher::vector_length_in_bytes(n) <= 16); ++ match(Set dst (RoundVF src)); ++ effect(TEMP_DEF dst, TEMP vtemp1, TEMP vtemp2); ++ format %{ "round_float_lsx $dst, $src\t# " ++ "TEMP($vtemp1, $vtemp2) @round_float_lsx" %} ++ ins_encode %{ ++ __ java_round_float_lsx($dst$$FloatRegister, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister, ++ $vtemp2$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct round_float_lasx(vReg dst, vReg src, vReg vtemp1, vReg vtemp2) %{ ++ predicate(Matcher::vector_length_in_bytes(n) > 16); ++ match(Set dst (RoundVF src)); ++ effect(TEMP_DEF dst, TEMP vtemp1, TEMP vtemp2); ++ format %{ "round_float_lasx $dst, $src\t# " ++ "TEMP($vtemp1, $vtemp2) @round_float_lasx" %} ++ ins_encode %{ ++ __ java_round_float_lasx($dst$$FloatRegister, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister, ++ $vtemp2$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct round_double_lsx(vReg dst, vReg src, vReg vtemp1, vReg vtemp2) %{ ++ predicate(Matcher::vector_length_in_bytes(n) <= 16); ++ match(Set dst (RoundVD src)); ++ effect(TEMP_DEF dst, TEMP vtemp1, TEMP vtemp2); ++ format %{ "round_double_lsx $dst, $src\t# " ++ "TEMP($vtemp1, $vtemp2) @round_double_lsx" %} ++ ins_encode %{ ++ __ java_round_double_lsx($dst$$FloatRegister, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister, ++ $vtemp2$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct round_double_lasx(vReg dst, vReg src, vReg vtemp1, vReg vtemp2) %{ ++ predicate(Matcher::vector_length_in_bytes(n) > 16); ++ match(Set dst (RoundVD src)); ++ effect(TEMP_DEF dst, TEMP vtemp1, TEMP vtemp2); ++ format %{ "round_double_lasx $dst, $src\t# " ++ "TEMP($vtemp1, $vtemp2) @round_double_lasx" %} ++ ins_encode %{ ++ __ java_round_double_lasx($dst$$FloatRegister, ++ $src$$FloatRegister, ++ $vtemp1$$FloatRegister, ++ $vtemp2$$FloatRegister); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +// ------------------------------ RoundDoubleModeV ---------------------------- + +instruct roundVD(vReg dst, vReg src, immI rmode) %{ @@ -41330,6 +41528,54 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++// ---------------------------- Vector UCast B2X ------------------------------- ++ ++instruct cvtVUB(vReg dst, vReg src) %{ ++ match(Set dst (VectorUCastB2X src)); ++ format %{ "(x)vconvert $dst, $src\t# @cvtVUB" %} ++ ins_encode %{ ++ switch (Matcher::vector_element_basic_type(this)) { ++ case T_SHORT : __ vext2xv_hu_bu($dst$$FloatRegister, $src$$FloatRegister); break; ++ case T_INT : __ vext2xv_wu_bu($dst$$FloatRegister, $src$$FloatRegister); break; ++ case T_LONG : __ vext2xv_du_bu($dst$$FloatRegister, $src$$FloatRegister); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++// ---------------------------- Vector UCast S2X ------------------------------- ++ ++instruct cvtVUS(vReg dst, vReg src) %{ ++ match(Set dst (VectorUCastS2X src)); ++ format %{ "(x)vconvert $dst, $src\t# @cvtVUS" %} ++ ins_encode %{ ++ switch (Matcher::vector_element_basic_type(this)) { ++ case T_INT : __ vext2xv_wu_hu($dst$$FloatRegister, $src$$FloatRegister); break; ++ case T_LONG : __ vext2xv_du_hu($dst$$FloatRegister, $src$$FloatRegister); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++// ---------------------------- Vector UCast I2X ------------------------------- ++ ++instruct cvtVUI(vReg dst, vReg src) %{ ++ match(Set dst (VectorUCastI2X src)); ++ format %{ "(x)vconvert $dst, $src\t# @cvtVUI" %} ++ ins_encode %{ ++ switch (Matcher::vector_element_basic_type(this)) { ++ case T_LONG : __ vext2xv_du_wu($dst$$FloatRegister, $src$$FloatRegister); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +// ---------------------------- Vector Cast B2X ------------------------------- + +instruct cvtVB(vReg dst, vReg src) %{ @@ -41725,6 +41971,108 @@ index 00000000000..e48d7a6a063 + ins_pipe( pipe_slow ); +%} + ++// ---------------------------------- Extract -------------------------------- ++ ++instruct extractVUB(mRegI dst, vReg src, mRegI idx, vReg tmp) %{ ++ match(Set dst (ExtractUB src idx)); ++ effect(TEMP tmp); ++ format %{ "(x)vextract $dst, $src, $idx\t# @extractVUB" %} ++ ins_encode %{ ++ // Input "src" is a vector of boolean represented as ++ // bytes with 0x00/0x01 as element values. ++ // "idx" is expected to be in range. ++ ++ if (Matcher::vector_length_in_bytes(this, $src) > 16) { ++ __ xvreplgr2vr_b(fscratch, $idx$$Register); ++ __ xvpermi_q($tmp$$FloatRegister, $src$$FloatRegister, 0x01); ++ __ xvshuf_b(fscratch, $tmp$$FloatRegister, $src$$FloatRegister, fscratch); ++ } else { ++ __ vreplgr2vr_b(fscratch, $idx$$Register); ++ __ vshuf_b(fscratch, $src$$FloatRegister, $src$$FloatRegister, fscratch); ++ } ++ __ vpickve2gr_b($dst$$Register, fscratch, 0); ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct extractV(mRegI dst, vReg src, immIU5 idx) %{ ++ match(Set dst (ExtractUB src idx)); ++ match(Set dst (ExtractB src idx)); ++ match(Set dst (ExtractS src idx)); ++ match(Set dst (ExtractI src idx)); ++ format %{ "(x)vextract $dst, $src, $idx\t# @extractV" %} ++ ins_encode %{ ++ int idx = $idx$$constant; ++ FloatRegister src = $src$$FloatRegister; ++ ++ if (type2aelembytes(Matcher::vector_element_basic_type(this, $src)) == 1 && idx >= 16) { ++ idx = idx - 16; ++ src = fscratch; ++ __ xvpermi_q(fscratch, $src$$FloatRegister, 0x01); ++ } else if (type2aelembytes(Matcher::vector_element_basic_type(this, $src)) == 2 && idx >= 8) { ++ idx = idx - 8; ++ src = fscratch; ++ __ xvpermi_q(fscratch, $src$$FloatRegister, 0x01); ++ } ++ ++ switch (Matcher::vector_element_basic_type(this, $src)) { ++ case T_BOOLEAN: ++ case T_BYTE : __ vpickve2gr_b($dst$$Register, src, idx); break; ++ case T_SHORT : __ vpickve2gr_h($dst$$Register, src, idx); break; ++ case T_INT : Matcher::vector_length_in_bytes(this, $src) > 16 ? ++ __ xvpickve2gr_w($dst$$Register, src, idx) : ++ __ vpickve2gr_w($dst$$Register, src, idx); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct extractVL(mRegL dst, vReg src, immIU2 idx) %{ ++ match(Set dst (ExtractL src idx)); ++ format %{ "(x)vpickve2gr.d $dst, $src, $idx\t# @extractVL" %} ++ ins_encode %{ ++ switch (Matcher::vector_length(this, $src)) { ++ case 2: __ vpickve2gr_d($dst$$Register, $src$$FloatRegister, $idx$$constant); break; ++ case 4: __ xvpickve2gr_d($dst$$Register, $src$$FloatRegister, $idx$$constant); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct extractVF(regF dst, vReg src, immIU3 idx) %{ ++ match(Set dst (ExtractF src idx)); ++ format %{ "(x)vextract $dst, $src, $idx\t# @extractVF" %} ++ ins_encode %{ ++ switch (Matcher::vector_length(this, $src)) { ++ case 2: ++ case 4: __ vshuf4i_w($dst$$FloatRegister, $src$$FloatRegister, $idx$$constant); break; ++ case 8: __ xvpickve_w($dst$$FloatRegister, $src$$FloatRegister, $idx$$constant); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ ++instruct extractVD(regD dst, vReg src, immIU2 idx) %{ ++ match(Set dst (ExtractD src idx)); ++ format %{ "(x)vextract $dst, $src, $idx\t# @extractVD" %} ++ ins_encode %{ ++ int idx = $idx$$constant; ++ switch (Matcher::vector_length(this, $src)) { ++ case 2: __ vshuf4i_d($dst$$FloatRegister, $src$$FloatRegister, idx+2); break; ++ case 4: __ xvpickve_d($dst$$FloatRegister, $src$$FloatRegister, idx); break; ++ default: ++ ShouldNotReachHere(); ++ } ++ %} ++ ins_pipe( pipe_slow ); ++%} ++ +// -------------------------------- Vector Blend ------------------------------ + +instruct blendV(vReg dst, vReg src1, vReg src2, vReg mask) @@ -42606,10 +42954,10 @@ index 00000000000..e48d7a6a063 + diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp new file mode 100644 -index 00000000000..d132d5d1c42 +index 00000000000..1e23abc76f8 --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.cpp -@@ -0,0 +1,4127 @@ +@@ -0,0 +1,4279 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Loongson Technology. All rights reserved. @@ -42650,6 +42998,7 @@ index 00000000000..d132d5d1c42 +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" +#include "nativeInst_loongarch.hpp" ++#include "oops/compressedKlass.inline.hpp" +#include "oops/compressedOops.inline.hpp" +#include "oops/klass.inline.hpp" +#include "prims/methodHandles.hpp" @@ -45116,7 +45465,7 @@ index 00000000000..d132d5d1c42 + // Don't worry too much about pre-existing connections with the input regs. + +#ifndef PRODUCT -+ int* pst_counter = &SharedRuntime::_partial_subtype_ctr; ++ uint* pst_counter = &SharedRuntime::_partial_subtype_ctr; + ExternalAddress pst_counter_addr((address) pst_counter); +#endif //PRODUCT + @@ -46107,147 +46456,77 @@ index 00000000000..d132d5d1c42 +// } +// return len; +// } -+void MacroAssembler::count_positives(Register src, Register len, Register result, Register tmp1) { -+ Label Loop, Negative, Result, Done; ++void MacroAssembler::count_positives(Register src, Register len, Register result, ++ Register tmp1, Register tmp2) { ++ Label Loop, Negative, Once, Done; + -+ move(result, R0); -+ li(tmp1, 0x8080808080808080); ++ move(result, R0); ++ beqz(len, Done); ++ ++ addi_w(tmp2, len, -8); ++ blt(tmp2, R0, Once); ++ ++ li(tmp1, 0x8080808080808080); + + bind(Loop); + ldx_d(AT, src, result); + andr(AT, AT, tmp1); + bnez(AT, Negative); ++ addi_w(result, result, 8); ++ bge(tmp2, result, Loop); + -+ addi_d(result, result, 8); -+ blt(result, len, Loop); -+ b(Result); ++ beq(result, len, Done); ++ ldx_d(AT, src, tmp2); ++ andr(AT, AT, tmp1); ++ move(result, tmp2); + + bind(Negative); + ctz_d(AT, AT); -+ srai_d(AT, AT, 3); -+ add_d(result, result, AT); -+ -+ bind(Result); -+ blt(result, len, Done); -+ move(result, len); -+ -+ bind(Done); -+} -+ -+void MacroAssembler::count_positives_v(Register src, Register len, Register result, Register tmp1) { -+ Label Loop, Negative, Result, Done; -+ -+ move(result, R0); -+ li(tmp1, (u1)16); -+ -+ bind(Loop); -+ vldx(fscratch, src, result); -+ vfrstpi_b(fscratch, fscratch, 0); -+ vpickve2gr_bu(AT, fscratch, 0); -+ bne(tmp1, AT, Negative); -+ -+ add_d(result, result, tmp1); -+ blt(result, len, Loop); -+ b(Result); -+ -+ bind(Negative); -+ add_d(result, result, AT); ++ srai_w(AT, AT, 3); ++ add_w(result, result, AT); ++ b(Done); + -+ bind(Result); -+ blt(result, len, Done); -+ move(result, len); ++ bind(Once); ++ ldx_b(tmp1, src, result); ++ blt(tmp1, R0, Done); ++ addi_w(result, result, 1); ++ blt(result, len, Once); + + bind(Done); +} + -+// Compress char[] to byte[]. len must be positive int. ++// Intrinsic for java.lang.StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) ++// Return the array length if every element in array can be encoded, ++// otherwise, the index of first non-latin1 (> 0xff) character. +// jtreg: TestStringIntrinsicRangeChecks.java +void MacroAssembler::char_array_compress(Register src, Register dst, + Register len, Register result, -+ Register tmp1, Register tmp2, -+ Register tmp3) { -+ Label Loop, Done, Once, Fail; -+ -+ move(result, len); -+ bge(R0, result, Done); -+ -+ srli_w(AT, len, 2); -+ andi(len, len, 3); -+ -+ li(tmp3, 0xff00ff00ff00ff00); -+ -+ bind(Loop); -+ beqz(AT, Once); -+ ld_d(tmp1, src, 0); -+ andr(tmp2, tmp3, tmp1); // not latin-1, stop here -+ bnez(tmp2, Fail); -+ -+ // 0x00a100b200c300d4 -> 0x00000000a1b2c3d4 -+ srli_d(tmp2, tmp1, 8); -+ orr(tmp2, tmp2, tmp1); // 0x00a1a1b2b2c3c3d4 -+ bstrpick_d(tmp1, tmp2, 47, 32); // 0x0000a1b2 -+ slli_d(tmp1, tmp1, 16); // 0xa1b20000 -+ bstrins_d(tmp1, tmp2, 15, 0); // 0xa1b2c3d4 -+ -+ st_w(tmp1, dst, 0); -+ addi_w(AT, AT, -1); -+ addi_d(dst, dst, 4); -+ addi_d(src, src, 8); -+ b(Loop); -+ -+ bind(Once); -+ beqz(len, Done); -+ ld_d(AT, src, 0); -+ -+ bstrpick_d(tmp1, AT, 15, 0); -+ andr(tmp2, tmp3, tmp1); -+ bnez(tmp2, Fail); -+ st_b(tmp1, dst, 0); -+ addi_w(len, len, -1); -+ -+ beqz(len, Done); -+ bstrpick_d(tmp1, AT, 31, 16); -+ andr(tmp2, tmp3, tmp1); -+ bnez(tmp2, Fail); -+ st_b(tmp1, dst, 1); -+ addi_w(len, len, -1); -+ -+ beqz(len, Done); -+ bstrpick_d(tmp1, AT, 47, 32); -+ andr(tmp2, tmp3, tmp1); -+ bnez(tmp2, Fail); -+ st_b(tmp1, dst, 2); -+ b(Done); -+ -+ bind(Fail); -+ move(result, R0); -+ -+ bind(Done); ++ Register tmp1, Register tmp2, Register tmp3, ++ FloatRegister vtemp1, FloatRegister vtemp2, ++ FloatRegister vtemp3, FloatRegister vtemp4) { ++ encode_iso_array(src, dst, len, result, tmp1, tmp2, tmp3, false, vtemp1, vtemp2, vtemp3, vtemp4); +} + +// Inflate byte[] to char[]. len must be positive int. +// jtreg:test/jdk/sun/nio/cs/FindDecoderBugs.java +void MacroAssembler::byte_array_inflate(Register src, Register dst, Register len, ++ Register tmp1, Register tmp2, + FloatRegister vtemp1, FloatRegister vtemp2) { -+ Label L_loop, L_small, L_last, L_done; ++ Label L_loop, L_small, L_small_loop, L_last, L_done; + + bge(R0, len, L_done); + -+ // the register AT stores the number of the loop -+ srli_w(AT, len, 4); -+ // the register len stores the remainder,less than 16 -+ andi(len, len, 15); ++ addi_w(tmp2, len, -16); ++ blt(tmp2, R0, L_small); + ++ move(tmp1, R0); ++ alsl_d(AT, len, dst, 0); // AT = dst + len * 2 + vxor_v(fscratch, fscratch, fscratch); + -+ // inflating 16 chars in one loop ++ // load and inflate 16 chars per loop + bind(L_loop); -+ // Short strings:less than 16 bytes -+ beqz(AT, L_small); -+ -+ vld(vtemp1, src, 0); -+ addi_w(AT, AT, -1); -+ addi_d(src, src, 16); ++ vldx(vtemp1, src, tmp1); ++ addi_w(tmp1, tmp1, 16); + + // 0x0000000000000000a1b2c3d4e5f6g7h8 -> 0x00a100b200c300d4..... + vilvl_b(vtemp2, fscratch, vtemp1); @@ -46258,35 +46537,54 @@ index 00000000000..d132d5d1c42 + vst(vtemp1, dst, 16); + + addi_d(dst, dst, 32); -+ b(L_loop); ++ bge(tmp2, tmp1, L_loop); ++ ++ // inflate the last 16 chars ++ beq(len, tmp1, L_done); ++ addi_d(AT, AT, -32); ++ vldx(vtemp1, src, tmp2); ++ vilvl_b(vtemp2, fscratch, vtemp1); ++ vst(vtemp2, AT, 0); ++ vilvh_b(vtemp1, fscratch, vtemp1); ++ vst(vtemp1, AT, 16); ++ b(L_done); + + bind(L_small); -+ -+ beqz(len, L_done); -+ -+ li(AT, 8); ++ li(AT, 4); + blt(len, AT, L_last); + -+ vld(vtemp1, src, 0); -+ addi_w(len, len, -8); -+ addi_d(src, src , 8); -+ -+ vilvl_b(vtemp1, fscratch, vtemp1); -+ vst(vtemp1, dst, 0); -+ -+ addi_d(dst, dst, 16); -+ -+ bind(L_last); -+ -+ beqz(len, L_done); ++ bind(L_small_loop); ++ ld_wu(tmp1, src, 0); ++ addi_d(src, src, 4); ++ addi_w(len, len, -4); ++ ++ // 0x00000000a1b2c3d4 -> 0x00a100b200c300d4 ++ bstrpick_d(tmp2, tmp1, 7, 0); ++ srli_d(tmp1, tmp1, 8); ++ bstrins_d(tmp2, tmp1, 23, 16); ++ srli_d(tmp1, tmp1, 8); ++ bstrins_d(tmp2, tmp1, 39, 32); ++ srli_d(tmp1, tmp1, 8); ++ bstrins_d(tmp2, tmp1, 55, 48); ++ ++ st_d(tmp2, dst, 0); ++ addi_d(dst, dst, 8); ++ bge(len, AT, L_small_loop); ++ ++ bind(L_last); ++ beqz(len, L_done); ++ ld_bu(AT, src, 0); ++ st_h(AT, dst, 0); ++ addi_w(len, len, -1); + -+ ld_bu(AT, src, 0); -+ st_h(AT, dst, 0); -+ addi_w(len, len, -1); -+ addi_d(src, src, 1); -+ addi_d(dst, dst, 2); ++ beqz(len, L_done); ++ ld_bu(AT, src, 1); ++ st_h(AT, dst, 2); ++ addi_w(len, len, -1); + -+ b(L_last); ++ beqz(len, L_done); ++ ld_bu(AT, src, 2); ++ st_h(AT, dst, 4); + + bind(L_done); +} @@ -46300,20 +46598,51 @@ index 00000000000..d132d5d1c42 +void MacroAssembler::encode_iso_array(Register src, Register dst, + Register len, Register result, + Register tmp1, Register tmp2, -+ Register tmp3, bool ascii) { -+ Label Loop, Done, Once; ++ Register tmp3, bool ascii, ++ FloatRegister vtemp1, FloatRegister vtemp2, ++ FloatRegister vtemp3, FloatRegister vtemp4) { ++ const FloatRegister shuf_index = vtemp3; ++ const FloatRegister latin_mask = vtemp4; + -+ move(result, R0); // init in case of bad value -+ bge(R0, len, Done); ++ Label Deal8, Loop8, Loop32, Done, Once; + -+ srai_w(AT, len, 2); ++ move(result, R0); // init in case of bad value ++ bge(R0, len, Done); + + li(tmp3, ascii ? 0xff80ff80ff80ff80 : 0xff00ff00ff00ff00); ++ srai_w(AT, len, 4); ++ beqz(AT, Deal8); + -+ bind(Loop); ++ li(tmp1, StubRoutines::la::string_compress_index()); ++ vld(shuf_index, tmp1, 0); ++ vreplgr2vr_d(latin_mask, tmp3); ++ ++ bind(Loop32); ++ beqz(AT, Deal8); ++ ++ vld(vtemp1, src, 0); ++ vld(vtemp2, src, 16); ++ addi_w(AT, AT, -1); ++ ++ vor_v(fscratch, vtemp1, vtemp2); ++ vand_v(fscratch, fscratch, latin_mask); ++ vseteqz_v(FCC0, fscratch); // not latin-1, apply slow path ++ bceqz(FCC0, Once); ++ ++ vshuf_b(fscratch, vtemp2, vtemp1, shuf_index); ++ ++ vstx(fscratch, dst, result); ++ addi_d(src, src, 32); ++ addi_w(result, result, 16); ++ b(Loop32); ++ ++ bind(Deal8); ++ bstrpick_w(AT, len, 3, 2); ++ ++ bind(Loop8); + beqz(AT, Once); + ld_d(tmp1, src, 0); -+ andr(tmp2, tmp3, tmp1); // not latin-1, stop here ++ andr(tmp2, tmp3, tmp1); // not latin-1, apply slow path + bnez(tmp2, Once); + + // 0x00a100b200c300d4 -> 0x00000000a1b2c3d4 @@ -46327,12 +46656,12 @@ index 00000000000..d132d5d1c42 + addi_w(AT, AT, -1); + addi_d(src, src, 8); + addi_w(result, result, 4); -+ b(Loop); ++ b(Loop8); + + bind(Once); + beq(len, result, Done); + ld_hu(tmp1, src, 0); -+ andr(tmp2, tmp3, tmp1); // not latin-1, stop here ++ andr(tmp2, tmp3, tmp1); // not latin-1, stop here + bnez(tmp2, Done); + stx_b(tmp1, dst, result); + addi_d(src, src, 2); @@ -46342,6 +46671,136 @@ index 00000000000..d132d5d1c42 + bind(Done); +} + ++// Math.round employs the ties-to-positive round mode, ++// which is not a typically conversion method defined ++// in the IEEE-754-2008. For single-precision floatings, ++// the following algorithm can be used to effectively ++// implement rounding via standard operations. ++void MacroAssembler::java_round_float(Register dst, ++ FloatRegister src, ++ FloatRegister vtemp1) { ++ block_comment("java_round_float: { "); ++ ++ Label L_abnormal, L_done; ++ ++ li(AT, StubRoutines::la::round_float_imm()); ++ ++ // if src is -0.5f, return 0 as result ++ fld_s(vtemp1, AT, 0); ++ fcmp_ceq_s(FCC0, vtemp1, src); ++ bceqz(FCC0, L_abnormal); ++ move(dst, R0); ++ b(L_done); ++ ++ // else, floor src with the magic number ++ bind(L_abnormal); ++ fld_s(vtemp1, AT, 4); ++ fadd_s(fscratch, vtemp1, src); ++ ftintrm_w_s(fscratch, fscratch); ++ movfr2gr_s(dst, fscratch); ++ ++ bind(L_done); ++ ++ block_comment("} java_round_float"); ++} ++ ++void MacroAssembler::java_round_float_lsx(FloatRegister dst, ++ FloatRegister src, ++ FloatRegister vtemp1, ++ FloatRegister vtemp2) { ++ block_comment("java_round_float_lsx: { "); ++ li(AT, StubRoutines::la::round_float_imm()); ++ vldrepl_w(vtemp1, AT, 0); // repl -0.5f ++ vldrepl_w(vtemp2, AT, 1); // repl 0.49999997f ++ ++ vfcmp_cne_s(fscratch, src, vtemp1); // generate the mask ++ vand_v(fscratch, fscratch, src); // clear the special ++ vfadd_s(dst, fscratch, vtemp2); // plus the magic ++ vftintrm_w_s(dst, dst); // floor the result ++ block_comment("} java_round_float_lsx"); ++} ++ ++void MacroAssembler::java_round_float_lasx(FloatRegister dst, ++ FloatRegister src, ++ FloatRegister vtemp1, ++ FloatRegister vtemp2) { ++ block_comment("java_round_float_lasx: { "); ++ li(AT, StubRoutines::la::round_float_imm()); ++ xvldrepl_w(vtemp1, AT, 0); // repl -0.5f ++ xvldrepl_w(vtemp2, AT, 1); // repl 0.49999997f ++ ++ xvfcmp_cne_s(fscratch, src, vtemp1); // generate the mask ++ xvand_v(fscratch, fscratch, src); // clear the special ++ xvfadd_s(dst, fscratch, vtemp2); // plus the magic ++ xvftintrm_w_s(dst, dst); // floor the result ++ block_comment("} java_round_float_lasx"); ++} ++ ++// Math.round employs the ties-to-positive round mode, ++// which is not a typically conversion method defined ++// in the IEEE-754-2008. For double-precision floatings, ++// the following algorithm can be used to effectively ++// implement rounding via standard operations. ++void MacroAssembler::java_round_double(Register dst, ++ FloatRegister src, ++ FloatRegister vtemp1) { ++ block_comment("java_round_double: { "); ++ ++ Label L_abnormal, L_done; ++ ++ li(AT, StubRoutines::la::round_double_imm()); ++ ++ // if src is -0.5d, return 0 as result ++ fld_d(vtemp1, AT, 0); ++ fcmp_ceq_d(FCC0, vtemp1, src); ++ bceqz(FCC0, L_abnormal); ++ move(dst, R0); ++ b(L_done); ++ ++ // else, floor src with the magic number ++ bind(L_abnormal); ++ fld_d(vtemp1, AT, 8); ++ fadd_d(fscratch, vtemp1, src); ++ ftintrm_l_d(fscratch, fscratch); ++ movfr2gr_d(dst, fscratch); ++ ++ bind(L_done); ++ ++ block_comment("} java_round_double"); ++} ++ ++void MacroAssembler::java_round_double_lsx(FloatRegister dst, ++ FloatRegister src, ++ FloatRegister vtemp1, ++ FloatRegister vtemp2) { ++ block_comment("java_round_double_lsx: { "); ++ li(AT, StubRoutines::la::round_double_imm()); ++ vldrepl_d(vtemp1, AT, 0); // repl -0.5d ++ vldrepl_d(vtemp2, AT, 1); // repl 0.49999999999999994d ++ ++ vfcmp_cne_d(fscratch, src, vtemp1); // generate the mask ++ vand_v(fscratch, fscratch, src); // clear the special ++ vfadd_d(dst, fscratch, vtemp2); // plus the magic ++ vftintrm_l_d(dst, dst); // floor the result ++ block_comment("} java_round_double_lsx"); ++} ++ ++void MacroAssembler::java_round_double_lasx(FloatRegister dst, ++ FloatRegister src, ++ FloatRegister vtemp1, ++ FloatRegister vtemp2) { ++ block_comment("java_round_double_lasx: { "); ++ li(AT, StubRoutines::la::round_double_imm()); ++ xvldrepl_d(vtemp1, AT, 0); // repl -0.5d ++ xvldrepl_d(vtemp2, AT, 1); // repl 0.49999999999999994d ++ ++ xvfcmp_cne_d(fscratch, src, vtemp1); // generate the mask ++ xvand_v(fscratch, fscratch, src); // clear the special ++ xvfadd_d(dst, fscratch, vtemp2); // plus the magic ++ xvftintrm_l_d(dst, dst); // floor the result ++ block_comment("} java_round_double_lasx"); ++} ++ +// Code for BigInteger::mulAdd intrinsic +// out = c_rarg0 +// in = c_rarg1 @@ -46414,6 +46873,47 @@ index 00000000000..d132d5d1c42 + bind(L_end); +} + ++// add two unsigned input and output carry ++void MacroAssembler::cad(Register dst, Register src1, Register src2, Register carry) ++{ ++ assert_different_registers(dst, carry); ++ assert_different_registers(dst, src2); ++ add_d(dst, src1, src2); ++ sltu(carry, dst, src2); ++} ++ ++// add two input with carry ++void MacroAssembler::adc(Register dst, Register src1, Register src2, Register carry) { ++ assert_different_registers(dst, carry); ++ add_d(dst, src1, src2); ++ add_d(dst, dst, carry); ++} ++ ++// add two unsigned input with carry and output carry ++void MacroAssembler::cadc(Register dst, Register src1, Register src2, Register carry) { ++ assert_different_registers(dst, src2); ++ adc(dst, src1, src2, carry); ++ sltu(carry, dst, src2); ++} ++ ++// Multiply and multiply-accumulate unsigned 64-bit registers. ++void MacroAssembler::wide_mul(Register prod_lo, Register prod_hi, Register n, Register m) { ++ assert_different_registers(prod_lo, prod_hi); ++ ++ mul_d(prod_lo, n, m); ++ mulh_du(prod_hi, n, m); ++} ++ ++void MacroAssembler::wide_madd(Register sum_lo, Register sum_hi, Register n, ++ Register m, Register tmp1, Register tmp2) { ++ assert_different_registers(sum_lo, sum_hi); ++ assert_different_registers(sum_hi, tmp2); ++ ++ wide_mul(tmp1, tmp2, n, m); ++ cad(sum_lo, sum_lo, tmp1, tmp1); // Add tmp1 to sum_lo with carry output to tmp1 ++ adc(sum_hi, sum_hi, tmp2, tmp1); // Add tmp2 with carry to sum_hi ++} ++ +#ifndef PRODUCT +void MacroAssembler::verify_cross_modify_fence_not_required() { + if (VerifyCrossModifyFence) { @@ -46592,7 +47092,7 @@ index 00000000000..d132d5d1c42 + } +} + -+// Implements fast-locking. ++// Implements lightweight-locking. +// Branches to slow upon failure to lock the object. +// Falls through upon success. +// @@ -46600,7 +47100,7 @@ index 00000000000..d132d5d1c42 +// - 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::fast_lock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { ++void MacroAssembler::lightweight_lock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { + assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking"); + assert_different_registers(obj, hdr, flag, tmp); + @@ -46625,7 +47125,7 @@ index 00000000000..d132d5d1c42 + st_w(tmp, Address(TREG, JavaThread::lock_stack_top_offset())); +} + -+// Implements fast-unlocking. ++// Implements lightweight-unlocking. +// Branches to slow upon failure. +// Falls through upon success. +// @@ -46633,7 +47133,7 @@ index 00000000000..d132d5d1c42 +// - 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::fast_unlock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { ++void MacroAssembler::lightweight_unlock(Register obj, Register hdr, Register flag, Register tmp, Label& slow) { + assert(LockingMode == LM_LIGHTWEIGHT, "only used with new lightweight locking"); + assert_different_registers(obj, hdr, tmp, flag); + @@ -46739,10 +47239,10 @@ index 00000000000..d132d5d1c42 +#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..b53a37c0af7 +index 00000000000..dbed82cd653 --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.hpp -@@ -0,0 +1,787 @@ +@@ -0,0 +1,815 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -47060,6 +47560,20 @@ index 00000000000..b53a37c0af7 + void sign_extend_short(Register reg) { ext_w_h(reg, reg); } + void sign_extend_byte(Register reg) { ext_w_b(reg, reg); } + ++ // java.lang.Math::round intrinsics ++ void java_round_float(Register dst, FloatRegister src, ++ FloatRegister vtemp1); ++ void java_round_float_lsx(FloatRegister dst, FloatRegister src, ++ FloatRegister vtemp1, FloatRegister vtemp2); ++ void java_round_float_lasx(FloatRegister dst, FloatRegister src, ++ FloatRegister vtemp1, FloatRegister vtemp2); ++ void java_round_double(Register dst, FloatRegister src, ++ FloatRegister vtemp1); ++ void java_round_double_lsx(FloatRegister dst, FloatRegister src, ++ FloatRegister vtemp1, FloatRegister vtemp2); ++ void java_round_double_lasx(FloatRegister dst, FloatRegister src, ++ FloatRegister vtemp1, FloatRegister vtemp2); ++ + // allocation + void tlab_allocate( + Register obj, // result: pointer to object after successful allocation @@ -47414,16 +47928,19 @@ index 00000000000..b53a37c0af7 + void kernel_crc32c(Register crc, Register buf, Register len, Register tmp); + + // Code for java.lang.StringCoding::countPositives intrinsic. -+ void count_positives(Register src, Register len, Register result, Register tmp1); -+ void count_positives_v(Register src, Register len, Register result, Register tmp1); ++ void count_positives(Register src, Register len, Register result, ++ Register tmp1, Register tmp2); + + // Code for java.lang.StringUTF16::compress intrinsic. -+ void char_array_compress(Register src, Register dst, Register len, -+ Register result, Register tmp1, -+ Register tmp2, Register tmp3); ++ void char_array_compress(Register src, Register dst, ++ Register len, Register result, ++ Register tmp1, Register tmp2, Register tmp3, ++ FloatRegister vtemp1, FloatRegister vtemp2, ++ FloatRegister vtemp3, FloatRegister vtemp4); + + // Code for java.lang.StringLatin1::inflate intrinsic. + void byte_array_inflate(Register src, Register dst, Register len, ++ Register tmp1, Register tmp2, + FloatRegister vtemp1, FloatRegister vtemp2); + + // Encode UTF16 to ISO_8859_1 or ASCII. @@ -47431,14 +47948,25 @@ index 00000000000..b53a37c0af7 + void encode_iso_array(Register src, Register dst, + Register len, Register result, + Register tmp1, Register tmp2, -+ Register tmp3, bool ascii); ++ Register tmp3, bool ascii, ++ FloatRegister vtemp1, FloatRegister vtemp2, ++ FloatRegister vtemp3, FloatRegister vtemp4); + + // Code for java.math.BigInteger::mulAdd intrinsic. + void mul_add(Register out, Register in, Register offset, + Register len, Register k); ++ void cad(Register dst, Register src1, Register src2, Register carry); ++ void cadc(Register dst, Register src1, Register src2, Register carry); ++ void adc(Register dst, Register src1, Register src2, Register carry); ++ void wide_mul(Register prod_lo, Register prod_hi, Register n, Register m); ++ void wide_madd(Register sum_lo, Register sum_hi, Register n, ++ Register m, Register tmp1, Register tmp2); + + void movoop(Register dst, jobject obj); + ++ // Helpers for the array_fill() macro ++ inline void tiny_fill_0_24(Register to, Register value); ++ + // Inner part of the generate_fill() stub + inline void array_fill(BasicType t, Register to, + Register value, Register count, bool aligned); @@ -47464,8 +47992,8 @@ index 00000000000..b53a37c0af7 + } + } + -+ void fast_lock(Register obj, Register hdr, Register flag, Register tmp, Label& slow); -+ void fast_unlock(Register obj, Register hdr, Register flag, Register tmp, Label& slow); ++ 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); + +#if INCLUDE_ZGC + void patchable_li16(Register rd, uint16_t value); @@ -47532,10 +48060,10 @@ index 00000000000..b53a37c0af7 +#endif // CPU_LOONGARCH_MACROASSEMBLER_LOONGARCH_HPP diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp new file mode 100644 -index 00000000000..07f81201557 +index 00000000000..43b388a2c4b --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch.inline.hpp -@@ -0,0 +1,1223 @@ +@@ -0,0 +1,937 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, Loongson Technology. All rights reserved. @@ -47569,12 +48097,162 @@ index 00000000000..07f81201557 +#include "asm/codeBuffer.hpp" +#include "code/codeCache.hpp" + ++inline void MacroAssembler::tiny_fill_0_24(Register to, Register value) { ++ // 0: ++ jr(RA); ++ nop(); ++ nop(); ++ nop(); ++ ++ // 1: ++ st_b(value, to, 0); ++ jr(RA); ++ nop(); ++ nop(); ++ ++ // 2: ++ st_h(value, to, 0); ++ jr(RA); ++ nop(); ++ nop(); ++ ++ // 3: ++ st_h(value, to, 0); ++ st_b(value, to, 2); ++ jr(RA); ++ nop(); ++ ++ // 4: ++ st_w(value, to, 0); ++ jr(RA); ++ nop(); ++ nop(); ++ ++ // 5: ++ st_w(value, to, 0); ++ st_b(value, to, 4); ++ jr(RA); ++ nop(); ++ ++ // 6: ++ st_w(value, to, 0); ++ st_h(value, to, 4); ++ jr(RA); ++ nop(); ++ ++ // 7: ++ st_w(value, to, 0); ++ st_w(value, to, 3); ++ jr(RA); ++ nop(); ++ ++ // 8: ++ st_d(value, to, 0); ++ jr(RA); ++ nop(); ++ nop(); ++ ++ // 9: ++ st_d(value, to, 0); ++ st_b(value, to, 8); ++ jr(RA); ++ nop(); ++ ++ // 10: ++ st_d(value, to, 0); ++ st_h(value, to, 8); ++ jr(RA); ++ nop(); ++ ++ // 11: ++ st_d(value, to, 0); ++ st_w(value, to, 7); ++ jr(RA); ++ nop(); ++ ++ // 12: ++ st_d(value, to, 0); ++ st_w(value, to, 8); ++ jr(RA); ++ nop(); ++ ++ // 13: ++ st_d(value, to, 0); ++ st_d(value, to, 5); ++ jr(RA); ++ nop(); ++ ++ // 14: ++ st_d(value, to, 0); ++ st_d(value, to, 6); ++ jr(RA); ++ nop(); ++ ++ // 15: ++ st_d(value, to, 0); ++ st_d(value, to, 7); ++ jr(RA); ++ nop(); ++ ++ // 16: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ jr(RA); ++ nop(); ++ ++ // 17: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_b(value, to, 16); ++ jr(RA); ++ ++ // 18: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_h(value, to, 16); ++ jr(RA); ++ ++ // 19: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_w(value, to, 15); ++ jr(RA); ++ ++ // 20: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_w(value, to, 16); ++ jr(RA); ++ ++ // 21: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_d(value, to, 13); ++ jr(RA); ++ ++ // 22: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_d(value, to, 14); ++ jr(RA); ++ ++ // 23: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_d(value, to, 15); ++ jr(RA); ++ ++ // 24: ++ st_d(value, to, 0); ++ st_d(value, to, 8); ++ st_d(value, to, 16); ++ jr(RA); ++} ++ +inline void MacroAssembler::array_fill(BasicType t, Register to, + Register value, Register count, + bool aligned) { -+ assert_different_registers(to, value, count, SCR1, SCR2); -+ -+ const Register end = SCR2; ++ assert_different_registers(to, value, count, SCR1); + + Label L_small; + @@ -47587,7 +48265,8 @@ index 00000000000..07f81201557 + bstrins_d(value, value, 31, 16); // 16 bit -> 32 bit + bstrins_d(value, value, 63, 32); // 32 bit -> 64 bit + bnez(SCR1, L_small); -+ add_d(end, to, count); ++ // count denotes the end, in bytes ++ add_d(count, to, count); + break; + case T_SHORT: + shift = 1; @@ -47595,20 +48274,23 @@ index 00000000000..07f81201557 + bstrins_d(value, value, 31, 16); // 16 bit -> 32 bit + bstrins_d(value, value, 63, 32); // 32 bit -> 64 bit + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_INT: + shift = 2; + slti(SCR1, count, 7); + bstrins_d(value, value, 63, 32); // 32 bit -> 64 bit + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_LONG: + shift = 3; + slti(SCR1, count, 4); + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + default: ShouldNotReachHere(); + } @@ -47623,7 +48305,7 @@ index 00000000000..07f81201557 + // fill large chunks + Label L_loop64, L_lt64, L_lt32, L_lt16, L_lt8; + -+ addi_d(SCR1, end, -64); ++ addi_d(SCR1, count, -64); + blt(SCR1, to, L_lt64); + + bind(L_loop64); @@ -47639,7 +48321,7 @@ index 00000000000..07f81201557 + bge(SCR1, to, L_loop64); + + bind(L_lt64); -+ addi_d(SCR1, end, -32); ++ addi_d(SCR1, count, -32); + blt(SCR1, to, L_lt32); + st_d(value, to, 0); + st_d(value, to, 8); @@ -47648,186 +48330,36 @@ index 00000000000..07f81201557 + addi_d(to, to, 32); + + bind(L_lt32); -+ addi_d(SCR1, end, -16); ++ addi_d(SCR1, count, -16); + blt(SCR1, to, L_lt16); + st_d(value, to, 0); + st_d(value, to, 8); + addi_d(to, to, 16); + + bind(L_lt16); -+ addi_d(SCR1, end, -8); ++ addi_d(SCR1, count, -8); + blt(SCR1, to, L_lt8); + st_d(value, to, 0); + + bind(L_lt8); -+ st_d(value, end, -8); ++ st_d(value, count, -8); + + jr(RA); + + // Short arrays (<= 24 bytes) + bind(L_small); + pcaddi(SCR1, 4); -+ slli_d(SCR2, count, 4 + shift); -+ add_d(SCR1, SCR1, SCR2); ++ slli_d(count, count, 4 + shift); ++ add_d(SCR1, SCR1, count); + jr(SCR1); + -+ // 0: -+ jr(RA); -+ nop(); -+ nop(); -+ nop(); -+ -+ // 1: -+ st_b(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 2: -+ st_h(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 3: -+ st_h(value, to, 0); -+ st_b(value, to, 2); -+ jr(RA); -+ nop(); -+ -+ // 4: -+ st_w(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 5: -+ st_w(value, to, 0); -+ st_b(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 6: -+ st_w(value, to, 0); -+ st_h(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 7: -+ st_w(value, to, 0); -+ st_w(value, to, 3); -+ jr(RA); -+ nop(); -+ -+ // 8: -+ st_d(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 9: -+ st_d(value, to, 0); -+ st_b(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 10: -+ st_d(value, to, 0); -+ st_h(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 11: -+ st_d(value, to, 0); -+ st_w(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 12: -+ st_d(value, to, 0); -+ st_w(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 13: -+ st_d(value, to, 0); -+ st_d(value, to, 5); -+ jr(RA); -+ nop(); -+ -+ // 14: -+ st_d(value, to, 0); -+ st_d(value, to, 6); -+ jr(RA); -+ nop(); -+ -+ // 15: -+ st_d(value, to, 0); -+ st_d(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 16: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 17: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_b(value, to, 16); -+ jr(RA); -+ -+ // 18: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_h(value, to, 16); -+ jr(RA); -+ -+ // 19: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_w(value, to, 15); -+ jr(RA); -+ -+ // 20: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_w(value, to, 16); -+ jr(RA); -+ -+ // 21: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_d(value, to, 13); -+ jr(RA); -+ -+ // 22: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_d(value, to, 14); -+ jr(RA); -+ -+ // 23: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_d(value, to, 15); -+ jr(RA); -+ -+ // 24: -+ st_d(value, to, 0); -+ st_d(value, to, 8); -+ st_d(value, to, 16); -+ jr(RA); ++ tiny_fill_0_24(to, value); +} + +inline void MacroAssembler::array_fill_lsx(BasicType t, Register to, + Register value, Register count) { + assert(UseLSX, "should be"); -+ assert_different_registers(to, value, count, SCR1, SCR2); -+ -+ const Register end = SCR2; ++ assert_different_registers(to, value, count, SCR1); + + Label L_small; + @@ -47839,7 +48371,8 @@ index 00000000000..07f81201557 + vreplgr2vr_b(fscratch, value); // 8 bit -> 128 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ add_d(end, to, count); ++ // count denotes the end, in bytes ++ add_d(count, to, count); + break; + case T_SHORT: + shift = 1; @@ -47847,7 +48380,8 @@ index 00000000000..07f81201557 + vreplgr2vr_h(fscratch, value); // 16 bit -> 128 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_INT: + shift = 2; @@ -47855,14 +48389,16 @@ index 00000000000..07f81201557 + vreplgr2vr_w(fscratch, value); // 32 bit -> 128 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_LONG: + shift = 3; + slti(SCR1, count, 7); + vreplgr2vr_d(fscratch, value); // 64 bit -> 128 bit + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + default: ShouldNotReachHere(); + } @@ -47875,7 +48411,7 @@ index 00000000000..07f81201557 + // fill large chunks + Label L_loop128, L_lt128, L_lt64, L_lt32, L_lt16; + -+ addi_d(SCR1, end, -128); ++ addi_d(SCR1, count, -128); + blt(SCR1, to, L_lt128); + + bind(L_loop128); @@ -47891,7 +48427,7 @@ index 00000000000..07f81201557 + bge(SCR1, to, L_loop128); + + bind(L_lt128); -+ addi_d(SCR1, end, -64); ++ addi_d(SCR1, count, -64); + blt(SCR1, to, L_lt64); + vst(fscratch, to, 0); + vst(fscratch, to, 16); @@ -47900,178 +48436,30 @@ index 00000000000..07f81201557 + addi_d(to, to, 64); + + bind(L_lt64); -+ addi_d(SCR1, end, -32); ++ addi_d(SCR1, count, -32); + blt(SCR1, to, L_lt32); + vst(fscratch, to, 0); + vst(fscratch, to, 16); + addi_d(to, to, 32); + + bind(L_lt32); -+ addi_d(SCR1, end, -16); ++ addi_d(SCR1, count, -16); + blt(SCR1, to, L_lt16); + vst(fscratch, to, 0); + + bind(L_lt16); -+ vst(fscratch, end, -16); ++ vst(fscratch, count, -16); + + jr(RA); + + // Short arrays (<= 48 bytes) + bind(L_small); + pcaddi(SCR1, 4); -+ slli_d(SCR2, count, 4 + shift); -+ add_d(SCR1, SCR1, SCR2); ++ slli_d(count, count, 4 + shift); ++ add_d(SCR1, SCR1, count); + jr(SCR1); + -+ // 0: -+ jr(RA); -+ nop(); -+ nop(); -+ nop(); -+ -+ // 1: -+ st_b(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 2: -+ st_h(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 3: -+ st_h(value, to, 0); -+ st_b(value, to, 2); -+ jr(RA); -+ nop(); -+ -+ // 4: -+ st_w(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 5: -+ st_w(value, to, 0); -+ st_b(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 6: -+ st_w(value, to, 0); -+ st_h(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 7: -+ st_w(value, to, 0); -+ st_w(value, to, 3); -+ jr(RA); -+ nop(); -+ -+ // 8: -+ st_d(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 9: -+ st_d(value, to, 0); -+ st_b(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 10: -+ st_d(value, to, 0); -+ st_h(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 11: -+ st_d(value, to, 0); -+ st_w(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 12: -+ st_d(value, to, 0); -+ st_w(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 13: -+ st_d(value, to, 0); -+ st_d(value, to, 5); -+ jr(RA); -+ nop(); -+ -+ // 14: -+ st_d(value, to, 0); -+ st_d(value, to, 6); -+ jr(RA); -+ nop(); -+ -+ // 15: -+ st_d(value, to, 0); -+ st_d(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 16: -+ vst(fscratch, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 17: -+ vst(fscratch, to, 0); -+ st_b(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 18: -+ vst(fscratch, to, 0); -+ st_h(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 19: -+ vst(fscratch, to, 0); -+ st_w(value, to, 15); -+ jr(RA); -+ nop(); -+ -+ // 20: -+ vst(fscratch, to, 0); -+ st_w(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 21: -+ vst(fscratch, to, 0); -+ st_d(value, to, 13); -+ jr(RA); -+ nop(); -+ -+ // 22: -+ vst(fscratch, to, 0); -+ st_d(value, to, 14); -+ jr(RA); -+ nop(); -+ -+ // 23: -+ vst(fscratch, to, 0); -+ st_d(value, to, 15); -+ jr(RA); -+ nop(); -+ -+ // 24: -+ vst(fscratch, to, 0); -+ st_d(value, to, 16); -+ jr(RA); -+ nop(); ++ tiny_fill_0_24(to, value); + + // 25: + vst(fscratch, to, 0); @@ -48221,9 +48609,7 @@ index 00000000000..07f81201557 +inline void MacroAssembler::array_fill_lasx(BasicType t, Register to, + Register value, Register count) { + assert(UseLASX, "should be"); -+ assert_different_registers(to, value, count, SCR1, SCR2); -+ -+ const Register end = SCR2; ++ assert_different_registers(to, value, count, SCR1); + + Label L_small; + @@ -48235,7 +48621,8 @@ index 00000000000..07f81201557 + xvreplgr2vr_b(fscratch, value); // 8 bit -> 256 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ add_d(end, to, count); ++ // count denotes the end, in bytes ++ add_d(count, to, count); + break; + case T_SHORT: + shift = 1; @@ -48243,7 +48630,8 @@ index 00000000000..07f81201557 + xvreplgr2vr_h(fscratch, value); // 16 bit -> 256 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_INT: + shift = 2; @@ -48251,14 +48639,16 @@ index 00000000000..07f81201557 + xvreplgr2vr_w(fscratch, value); // 32 bit -> 256 bit + movfr2gr_d(value, fscratch); + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + case T_LONG: + shift = 3; + slti(SCR1, count, 10); + xvreplgr2vr_d(fscratch, value); // 64 bit -> 256 bit + bnez(SCR1, L_small); -+ alsl_d(end, count, to, shift - 1); ++ // count denotes the end, in bytes ++ alsl_d(count, count, to, shift - 1); + break; + default: ShouldNotReachHere(); + } @@ -48271,7 +48661,7 @@ index 00000000000..07f81201557 + // fill large chunks + Label L_loop256, L_lt256, L_lt128, L_lt64, L_lt32; + -+ addi_d(SCR1, end, -256); ++ addi_d(SCR1, count, -256); + blt(SCR1, to, L_lt256); + + bind(L_loop256); @@ -48287,7 +48677,7 @@ index 00000000000..07f81201557 + bge(SCR1, to, L_loop256); + + bind(L_lt256); -+ addi_d(SCR1, end, -128); ++ addi_d(SCR1, count, -128); + blt(SCR1, to, L_lt128); + xvst(fscratch, to, 0); + xvst(fscratch, to, 32); @@ -48296,178 +48686,30 @@ index 00000000000..07f81201557 + addi_d(to, to, 128); + + bind(L_lt128); -+ addi_d(SCR1, end, -64); ++ addi_d(SCR1, count, -64); + blt(SCR1, to, L_lt64); + xvst(fscratch, to, 0); + xvst(fscratch, to, 32); + addi_d(to, to, 64); + + bind(L_lt64); -+ addi_d(SCR1, end, -32); ++ addi_d(SCR1, count, -32); + blt(SCR1, to, L_lt32); + xvst(fscratch, to, 0); + + bind(L_lt32); -+ xvst(fscratch, end, -32); ++ xvst(fscratch, count, -32); + + jr(RA); + -+ // Short arrays (<= 48 bytes) ++ // Short arrays (<= 72 bytes) + bind(L_small); + pcaddi(SCR1, 4); -+ slli_d(SCR2, count, 4 + shift); -+ add_d(SCR1, SCR1, SCR2); ++ slli_d(count, count, 4 + shift); ++ add_d(SCR1, SCR1, count); + jr(SCR1); + -+ // 0: -+ jr(RA); -+ nop(); -+ nop(); -+ nop(); -+ -+ // 1: -+ st_b(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 2: -+ st_h(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 3: -+ st_h(value, to, 0); -+ st_b(value, to, 2); -+ jr(RA); -+ nop(); -+ -+ // 4: -+ st_w(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 5: -+ st_w(value, to, 0); -+ st_b(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 6: -+ st_w(value, to, 0); -+ st_h(value, to, 4); -+ jr(RA); -+ nop(); -+ -+ // 7: -+ st_w(value, to, 0); -+ st_w(value, to, 3); -+ jr(RA); -+ nop(); -+ -+ // 8: -+ st_d(value, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 9: -+ st_d(value, to, 0); -+ st_b(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 10: -+ st_d(value, to, 0); -+ st_h(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 11: -+ st_d(value, to, 0); -+ st_w(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 12: -+ st_d(value, to, 0); -+ st_w(value, to, 8); -+ jr(RA); -+ nop(); -+ -+ // 13: -+ st_d(value, to, 0); -+ st_d(value, to, 5); -+ jr(RA); -+ nop(); -+ -+ // 14: -+ st_d(value, to, 0); -+ st_d(value, to, 6); -+ jr(RA); -+ nop(); -+ -+ // 15: -+ st_d(value, to, 0); -+ st_d(value, to, 7); -+ jr(RA); -+ nop(); -+ -+ // 16: -+ vst(fscratch, to, 0); -+ jr(RA); -+ nop(); -+ nop(); -+ -+ // 17: -+ vst(fscratch, to, 0); -+ st_b(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 18: -+ vst(fscratch, to, 0); -+ st_h(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 19: -+ vst(fscratch, to, 0); -+ st_w(value, to, 15); -+ jr(RA); -+ nop(); -+ -+ // 20: -+ vst(fscratch, to, 0); -+ st_w(value, to, 16); -+ jr(RA); -+ nop(); -+ -+ // 21: -+ vst(fscratch, to, 0); -+ st_d(value, to, 13); -+ jr(RA); -+ nop(); -+ -+ // 22: -+ vst(fscratch, to, 0); -+ st_d(value, to, 14); -+ jr(RA); -+ nop(); -+ -+ // 23: -+ vst(fscratch, to, 0); -+ st_d(value, to, 15); -+ jr(RA); -+ nop(); -+ -+ // 24: -+ vst(fscratch, to, 0); -+ st_d(value, to, 16); -+ jr(RA); -+ nop(); ++ tiny_fill_0_24(to, value); + + // 25: + vst(fscratch, to, 0); @@ -50484,7 +50726,7 @@ 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..79b5d4157a8 +index 00000000000..012e781dba8 --- /dev/null +++ b/src/hotspot/cpu/loongarch/matcher_loongarch.hpp @@ -0,0 +1,181 @@ @@ -50524,7 +50766,7 @@ index 00000000000..79b5d4157a8 + // Whether this platform implements the scalable vector feature + static const bool implements_scalable_vector = false; + -+ static const bool supports_scalable_vector() { ++ static bool supports_scalable_vector() { + return false; + } + @@ -50624,7 +50866,7 @@ index 00000000000..79b5d4157a8 + } + + // Some microarchitectures have mask registers used on vectors -+ static const bool has_predicated_vectors(void) { ++ static bool has_predicated_vectors(void) { + return false; + } + @@ -52592,7 +52834,7 @@ 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..25f7abfe75e +index 00000000000..6ffdd41a5e7 --- /dev/null +++ b/src/hotspot/cpu/loongarch/register_loongarch.hpp @@ -0,0 +1,479 @@ @@ -52653,7 +52895,7 @@ index 00000000000..25f7abfe75e + + public: + // accessors -+ constexpr int raw_encoding() const { return this - first(); } ++ constexpr int raw_encoding() const { return checked_cast(this - first()); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + @@ -52823,7 +53065,7 @@ index 00000000000..25f7abfe75e + + public: + // accessors -+ constexpr int raw_encoding() const { return this - first(); } ++ constexpr int raw_encoding() const { return checked_cast(this - first()); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + @@ -52984,7 +53226,7 @@ index 00000000000..25f7abfe75e + + public: + // accessors -+ int raw_encoding() const { return this - first(); } ++ int raw_encoding() const { return checked_cast(this - first()); } + int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + @@ -53266,13 +53508,13 @@ 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..aab7f9f7071 +index 00000000000..23763cc6c78 --- /dev/null +++ b/src/hotspot/cpu/loongarch/sharedRuntime_loongarch_64.cpp -@@ -0,0 +1,2975 @@ +@@ -0,0 +1,2977 @@ +/* + * 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 @@ -53620,7 +53862,7 @@ index 00000000000..aab7f9f7071 + + uint int_args = 0; + uint fp_args = 0; -+ uint stk_args = 0; // inc by 2 each time ++ uint stk_args = 0; + + for (int i = 0; i < total_args_passed; i++) { + switch (sig_bt[i]) { @@ -53637,8 +53879,9 @@ index 00000000000..aab7f9f7071 + if (int_args < Argument::n_int_register_parameters_j) { + regs[i].set1(INT_ArgReg[int_args++]->as_VMReg()); + } else { ++ stk_args = align_up(stk_args, 2); + regs[i].set1(VMRegImpl::stack2reg(stk_args)); -+ stk_args += 2; ++ stk_args += 1; + } + break; + case T_LONG: @@ -53650,6 +53893,7 @@ index 00000000000..aab7f9f7071 + if (int_args < Argument::n_int_register_parameters_j) { + regs[i].set2(INT_ArgReg[int_args++]->as_VMReg()); + } else { ++ stk_args = align_up(stk_args, 2); + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } @@ -53658,8 +53902,9 @@ index 00000000000..aab7f9f7071 + if (fp_args < Argument::n_float_register_parameters_j) { + regs[i].set1(FP_ArgReg[fp_args++]->as_VMReg()); + } else { ++ stk_args = align_up(stk_args, 2); + regs[i].set1(VMRegImpl::stack2reg(stk_args)); -+ stk_args += 2; ++ stk_args += 1; + } + break; + case T_DOUBLE: @@ -53667,6 +53912,7 @@ index 00000000000..aab7f9f7071 + if (fp_args < Argument::n_float_register_parameters_j) { + regs[i].set2(FP_ArgReg[fp_args++]->as_VMReg()); + } else { ++ stk_args = align_up(stk_args, 2); + regs[i].set2(VMRegImpl::stack2reg(stk_args)); + stk_args += 2; + } @@ -53677,7 +53923,7 @@ index 00000000000..aab7f9f7071 + } + } + -+ return align_up(stk_args, 2); ++ return stk_args; +} + +// Patch the callers callsite with entry to compiled code if it exists. @@ -54024,9 +54270,7 @@ index 00000000000..aab7f9f7071 + +int SharedRuntime::c_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, -+ VMRegPair *regs2, + int total_args_passed) { -+ assert(regs2 == nullptr, "not needed on LA"); + + // We return the amount of VMRegImpl stack slots we need to reserve for all + // the arguments NOT counting out_preserve_stack_slots. @@ -54666,7 +54910,7 @@ index 00000000000..aab7f9f7071 + // the 1st six register arguments). It's weird see int_stk_helper. + // + int out_arg_slots; -+ out_arg_slots = c_calling_convention(out_sig_bt, out_regs, nullptr, total_c_args); ++ out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + + // Compute framesize for the wrapper. We need to handlize all oops in + // registers. We must create space for them here that is disjoint from @@ -55034,7 +55278,7 @@ index 00000000000..aab7f9f7071 + __ ld_d(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + // FIXME + Register tmp = T1; -+ __ fast_lock(obj_reg, swap_reg, tmp, SCR1, slow_path_lock); ++ __ lightweight_lock(obj_reg, swap_reg, tmp, SCR1, slow_path_lock); + } + + __ bind(count); @@ -55197,7 +55441,7 @@ index 00000000000..aab7f9f7071 + __ ld_d(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); + __ andi(AT, lock_reg, markWord::monitor_value); + __ bnez(AT, slow_path_unlock); -+ __ fast_unlock(obj_reg, lock_reg, swap_reg, SCR1, slow_path_unlock); ++ __ lightweight_unlock(obj_reg, lock_reg, swap_reg, SCR1, slow_path_unlock); + __ decrement(Address(TREG, JavaThread::held_monitor_count_offset())); + } + @@ -56345,7 +56589,7 @@ 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..d329c43d661 +index 00000000000..5034e2924cb --- /dev/null +++ b/src/hotspot/cpu/loongarch/stackChunkFrameStream_loongarch.inline.hpp @@ -0,0 +1,142 @@ @@ -56466,8 +56710,8 @@ index 00000000000..d329c43d661 + f.interpreted_frame_oop_map(&mask); + return mask.num_oops() + + 1 // for the mirror oop -+ + ((intptr_t*)f.interpreter_frame_monitor_begin() -+ - (intptr_t*)f.interpreter_frame_monitor_end()) / BasicObjectLock::size(); ++ + pointer_delta_as_int((intptr_t*)f.interpreter_frame_monitor_begin(), ++ (intptr_t*)f.interpreter_frame_monitor_end()) / BasicObjectLock::size(); +} + +template<> @@ -56542,10 +56786,10 @@ 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..7a85b1fd838 +index 00000000000..f9b95b56af8 --- /dev/null +++ b/src/hotspot/cpu/loongarch/stubGenerator_loongarch_64.cpp -@@ -0,0 +1,5737 @@ +@@ -0,0 +1,5952 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -56584,6 +56828,7 @@ index 00000000000..7a85b1fd838 +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" ++#include "prims/upcallLinker.hpp" +#include "runtime/continuation.hpp" +#include "runtime/continuationEntry.inline.hpp" +#include "runtime/frame.inline.hpp" @@ -56614,103 +56859,89 @@ index 00000000000..7a85b1fd838 + +#define __ _masm-> + -+#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8) -+ -+//#ifdef PRODUCT -+//#define BLOCK_COMMENT(str) /* nothing */ -+//#else -+//#define BLOCK_COMMENT(str) __ block_comment(str) -+//#endif ++#ifdef PRODUCT ++#define BLOCK_COMMENT(str) /* nothing */ ++#else ++#define BLOCK_COMMENT(str) __ block_comment(str) ++#endif + -+//#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -+const int MXCSR_MASK = 0xFFC0; // Mask out any pending exceptions ++#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +// Stub Code definitions + +class StubGenerator: public StubCodeGenerator { + private: + -+ // This fig is not LA ABI. It is call Java from C ABI. + // Call stubs are used to call Java from C + // -+ // [ return_from_Java ] -+ // [ argument word n-1 ] <--- sp -+ // ... -+ // [ argument word 0 ] -+ // ... -+ // -10 [ S6 ] -+ // -9 [ S5 ] -+ // -8 [ S4 ] -+ // -7 [ S3 ] -+ // -6 [ S1 ] -+ // -5 [ TSR(S2) ] -+ // -4 [ LVP(S7) ] -+ // -3 [ BCP(S0) ] -+ // -2 [ saved fp ] -+ // -1 [ return address ] -+ // 0 [ ptr. to call wrapper ] <--- a0 (old sp -->) fp -+ // 1 [ result ] <--- a1 -+ // 2 [ result_type ] <--- a2 -+ // 3 [ method ] <--- a3 -+ // 4 [ entry_point ] <--- a4 -+ // 5 [ parameters ] <--- a5 -+ // 6 [ parameter_size ] <--- a6 -+ // 7 [ thread ] <--- a7 -+ ++ // Arguments: ++ // c_rarg0: call wrapper address address ++ // c_rarg1: result address ++ // c_rarg2: result type BasicType ++ // c_rarg3: method Method* ++ // c_rarg4: (interpreter) entry point address ++ // c_rarg5: parameters intptr_t* ++ // c_rarg6: parameter size (in words) int ++ // c_rarg7: thread Thread* ++ // ++ // we don't need to save all arguments, since both C and Java treat ++ // them as volatile registers. ++ // ++ // we only need to keep call wrapper address (c_rarg0) for Java frame, ++ // and restore the stub result via c_rarg1 and c_rarg2. ++ // ++ // we save RA as the return PC at the base of the frame and link FP ++ // below it as the frame pointer. + // -+ // LA ABI does not save paras in sp. ++ // we save S0-S8 and F24-F31 which are expected to be callee-saved. + // -+ // [ return_from_Java ] -+ // [ argument word n-1 ] <--- sp ++ // so the stub frame looks like this when we enter Java code ++ // ++ // [ return_from_Java ] <--- sp ++ // [ argument word n ] + // ... -+ // [ argument word 0 ] -+ //-24 [ ] <--- sp_after_call -+ //-23 [ F31 ] ++ // -23 [ argument word 1 ] ++ // -22 [ F31 ] <--- sp_after_call + // ... -+ //-16 [ F24 ] -+ //-15 [ S8 ] -+ //-14 [ thread ] -+ //-13 [ result_type ] <--- a2 -+ //-12 [ result ] <--- a1 -+ //-11 [ ptr. to call wrapper ] <--- a0 -+ //-10 [ S6 ] -+ // -9 [ S5 ] -+ // -8 [ S4 ] -+ // -7 [ S3 ] -+ // -6 [ S1 ] -+ // -5 [ TSR(S2) ] -+ // -4 [ LVP(S7) ] -+ // -3 [ BCP(S0) ] -+ // -2 [ saved fp ] -+ // -1 [ return address ] -+ // 0 [ ] <--- old sp = fp_after_call -+ // ++ // -15 [ F24 ] ++ // -14 [ S8 ] ++ // ... ++ // -6 [ S0 ] ++ // -5 [ result_type ] <--- c_rarg2 ++ // -4 [ result ] <--- c_rarg1 ++ // -3 [ call wrapper ] <--- c_rarg0 ++ // -2 [ saved FP ] ++ // -1 [ saved RA ] ++ // 0 [ ] <--- fp ++ ++ // Call stub stack layout word offsets from fp + enum call_stub_layout { -+ RA_off = -1, ++ sp_after_call_off = -22, ++ ++ F31_off = -22, ++ F30_off = -21, ++ F29_off = -20, ++ F28_off = -19, ++ F27_off = -18, ++ F26_off = -17, ++ F25_off = -16, ++ F24_off = -15, ++ ++ S8_off = -14, ++ S7_off = -13, ++ S6_off = -12, ++ S5_off = -11, ++ S4_off = -10, ++ S3_off = -9, ++ S2_off = -8, ++ S1_off = -7, ++ S0_off = -6, ++ ++ result_type_off = -5, ++ result_off = -4, ++ call_wrapper_off = -3, + FP_off = -2, -+ BCP_off = -3, -+ LVP_off = -4, -+ TSR_off = -5, -+ S1_off = -6, -+ S3_off = -7, -+ S4_off = -8, -+ S5_off = -9, -+ S6_off = -10, -+ call_wrapper_off = -11, -+ result_off = -12, -+ result_type_off = -13, -+ thread_off = -14, -+ S8_off = -15, -+ F24_off = -16, -+ F25_off = -17, -+ F26_off = -18, -+ F27_off = -19, -+ F28_off = -20, -+ F29_off = -21, -+ F30_off = -22, -+ F31_off = -23, -+ // padding for SP 16-byte alignment -+ sp_after_call_off = -24, ++ RA_off = -1, + }; + + address generate_call_stub(address& return_address) { @@ -56728,18 +56959,19 @@ index 00000000000..7a85b1fd838 + __ enter(); + __ addi_d(SP, FP, sp_after_call_off * wordSize); + -+ __ st_d(BCP, FP, BCP_off * wordSize); -+ __ st_d(LVP, FP, LVP_off * wordSize); -+ __ st_d(TSR, FP, TSR_off * wordSize); ++ // save register parameters and Java temporary/global registers ++ __ st_d(A0, FP, call_wrapper_off * wordSize); ++ __ st_d(A1, FP, result_off * wordSize); ++ __ st_d(A2, FP, result_type_off * wordSize); ++ ++ __ st_d(S0, FP, S0_off * wordSize); + __ st_d(S1, FP, S1_off * wordSize); ++ __ st_d(S2, FP, S2_off * wordSize); + __ st_d(S3, FP, S3_off * wordSize); + __ st_d(S4, FP, S4_off * wordSize); + __ st_d(S5, FP, S5_off * wordSize); + __ st_d(S6, FP, S6_off * wordSize); -+ __ st_d(A0, FP, call_wrapper_off * wordSize); -+ __ st_d(A1, FP, result_off * wordSize); -+ __ st_d(A2, FP, result_type_off * wordSize); -+ __ st_d(A7, FP, thread_off * wordSize); ++ __ st_d(S7, FP, S7_off * wordSize); + __ st_d(S8, FP, S8_off * wordSize); + + __ fst_d(F24, FP, F24_off * wordSize); @@ -56755,7 +56987,10 @@ index 00000000000..7a85b1fd838 + // whatever value it held + __ move(TREG, A7); + -+ //add for compressedoops ++ // init Method* ++ __ move(Rmethod, A3); ++ ++ // set up the heapbase register + __ reinit_heapbase(); + +#ifdef ASSERT @@ -56770,80 +57005,71 @@ index 00000000000..7a85b1fd838 +#endif + + // pass parameters if any -+ // A5: parameter -+ // A6: parameter_size -+ // T0: parameter_size_tmp(--) -+ // T2: offset(++) -+ // T3: tmp ++ // c_rarg5: parameter_pointer ++ // c_rarg6: parameter_size + Label parameters_done; -+ // judge if the parameter_size equals 0 -+ __ beq(A6, R0, parameters_done); -+ __ slli_d(AT, A6, Interpreter::logStackElementSize); -+ __ sub_d(SP, SP, AT); ++ __ beqz(c_rarg6, parameters_done); ++ ++ __ slli_d(c_rarg6, c_rarg6, LogBytesPerWord); ++ __ sub_d(SP, SP, c_rarg6); + assert(StackAlignmentInBytes == 16, "must be"); + __ bstrins_d(SP, R0, 3, 0); -+ // Copy Java parameters in reverse order (receiver last) -+ // Note that the argument order is inverted in the process -+ Label loop; -+ __ move(T0, A6); -+ __ move(T2, R0); -+ __ bind(loop); + -+ // get parameter -+ __ alsl_d(T3, T0, A5, LogBytesPerWord - 1); -+ __ ld_d(AT, T3, -wordSize); -+ __ alsl_d(T3, T2, SP, LogBytesPerWord - 1); -+ __ st_d(AT, T3, Interpreter::expr_offset_in_bytes(0)); -+ __ addi_d(T2, T2, 1); -+ __ addi_d(T0, T0, -1); -+ __ bne(T0, R0, loop); -+ // advance to next parameter -+ -+ // call Java function ++ address loop = __ pc(); ++ __ ld_d(AT, c_rarg5, 0); ++ __ addi_d(c_rarg5, c_rarg5, wordSize); ++ __ addi_d(c_rarg6, c_rarg6, -wordSize); ++ __ stx_d(AT, SP, c_rarg6); ++ __ blt(R0, c_rarg6, loop); ++ + __ bind(parameters_done); + -+ // receiver in V0, Method* in Rmethod ++ // call Java entry -- passing methdoOop, and current sp ++ // Rmethod: Method* ++ // Rsender: sender sp ++ BLOCK_COMMENT("call Java function"); ++ __ move(Rsender, SP); ++ __ jalr(c_rarg4); ++ ++ // save current address for use by exception handling code + -+ __ move(Rmethod, A3); -+ __ move(Rsender, SP); //set sender sp -+ __ jalr(A4); + return_address = __ pc(); + + // store result depending on type (everything that is not + // T_OBJECT, T_LONG, T_FLOAT or T_DOUBLE is treated as T_INT) -+ // n.b. this assumes Java returns an integral result in V0 ++ // n.b. this assumes Java returns an integral result in A0 + // and a floating result in FA0 -+ __ ld_d(T0, FP, result_off * wordSize); -+ __ ld_d(T2, FP, result_type_off * wordSize); ++ __ ld_d(c_rarg1, FP, result_off * wordSize); ++ __ ld_d(c_rarg2, FP, result_type_off * wordSize); + + Label is_long, is_float, is_double, exit; + -+ __ addi_d(AT, T2, (-1) * T_OBJECT); ++ __ addi_d(AT, c_rarg2, (-1) * T_OBJECT); + __ beqz(AT, is_long); -+ __ addi_d(AT, T2, (-1) * T_LONG); ++ __ addi_d(AT, c_rarg2, (-1) * T_LONG); + __ beqz(AT, is_long); -+ __ addi_d(AT, T2, (-1) * T_FLOAT); ++ __ addi_d(AT, c_rarg2, (-1) * T_FLOAT); + __ beqz(AT, is_float); -+ __ addi_d(AT, T2, (-1) * T_DOUBLE); ++ __ addi_d(AT, c_rarg2, (-1) * T_DOUBLE); + __ beqz(AT, is_double); + + // handle T_INT case -+ __ st_w(V0, T0, 0); ++ __ st_w(A0, c_rarg1, 0); + + __ bind(exit); + + __ pop_cont_fastpath(TREG); + + // restore callee-save registers -+ __ ld_d(BCP, FP, BCP_off * wordSize); -+ __ ld_d(LVP, FP, LVP_off * wordSize); -+ __ ld_d(TSR, FP, TSR_off * wordSize); + ++ __ ld_d(S0, FP, S0_off * wordSize); + __ ld_d(S1, FP, S1_off * wordSize); ++ __ ld_d(S2, FP, S2_off * wordSize); + __ ld_d(S3, FP, S3_off * wordSize); + __ ld_d(S4, FP, S4_off * wordSize); + __ ld_d(S5, FP, S5_off * wordSize); + __ ld_d(S6, FP, S6_off * wordSize); ++ __ ld_d(S7, FP, S7_off * wordSize); + __ ld_d(S8, FP, S8_off * wordSize); + + __ fld_d(F24, FP, F24_off * wordSize); @@ -56861,15 +57087,15 @@ index 00000000000..7a85b1fd838 + + // handle return types different from T_INT + __ bind(is_long); -+ __ st_d(V0, T0, 0); ++ __ st_d(A0, c_rarg1, 0); + __ b(exit); + + __ bind(is_float); -+ __ fst_s(FA0, T0, 0); ++ __ fst_s(FA0, c_rarg1, 0); + __ b(exit); + + __ bind(is_double); -+ __ fst_d(FA0, T0, 0); ++ __ fst_d(FA0, c_rarg1, 0); + __ b(exit); + + return start; @@ -59457,6 +59683,9 @@ index 00000000000..7a85b1fd838 + StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill"); + StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill"); + ++ StubRoutines::la::_jlong_fill = generate_fill(T_LONG, false, "jlong_fill"); ++ StubRoutines::la::_arrayof_jlong_fill = generate_fill(T_LONG, true, "arrayof_jlong_fill"); ++ +#if INCLUDE_ZGC + if (!(UseZGC && ZGenerational)) { +#endif @@ -59476,9 +59705,9 @@ index 00000000000..7a85b1fd838 + Copy::_arrayof_conjoint_jints = reinterpret_cast(StubRoutines::arrayof_jint_arraycopy()); + Copy::_arrayof_conjoint_jlongs = reinterpret_cast(StubRoutines::arrayof_jlong_arraycopy()); + Copy::_arrayof_conjoint_oops = reinterpret_cast(StubRoutines::arrayof_jlong_arraycopy()); -+ Copy::_fill_to_words = reinterpret_cast(generate_fill(T_LONG, false, "jlong_fill")); -+ Copy::_fill_to_aligned_words = reinterpret_cast(generate_fill(T_LONG, true, "arrayof_jlong_fill"));; -+ Copy::_fill_to_bytes = reinterpret_cast(StubRoutines::_jbyte_fill); ++ Copy::_fill_to_bytes = reinterpret_cast(StubRoutines::jbyte_fill()); ++ Copy::_fill_to_words = reinterpret_cast(StubRoutines::la::jlong_fill()); ++ Copy::_fill_to_aligned_words = reinterpret_cast(StubRoutines::la::arrayof_jlong_fill());; +#if INCLUDE_ZGC + } +#endif @@ -61370,6 +61599,216 @@ index 00000000000..7a85b1fd838 + return start; + } + ++#ifdef COMPILER2 ++ ++static const int64_t right_2_bits = right_n_bits(2); ++static const int64_t right_3_bits = right_n_bits(3); ++ ++ // In sun.security.util.math.intpoly.IntegerPolynomial1305, integers ++ // are represented as long[5], with BITS_PER_LIMB = 26. ++ // Pack five 26-bit limbs into three 64-bit registers. ++ void poly1305_pack_26(Register dest0, Register dest1, Register dest2, Register src, Register tmp1, Register tmp2) { ++ assert_different_registers(dest0, dest1, dest2, src, tmp1, tmp2); ++ ++ // The goal is to have 128-bit value in dest2:dest1:dest0 ++ __ ld_d(dest0, Address(src, 0)); // 26 bits in dest0 ++ ++ __ ld_d(tmp1, Address(src, sizeof(jlong))); ++ __ slli_d(tmp1, tmp1, 26); ++ __ add_d(dest0, dest0, tmp1); // 52 bits in dest0 ++ ++ __ ld_d(tmp2, Address(src, 2 * sizeof(jlong))); ++ __ slli_d(tmp1, tmp2, 52); ++ __ add_d(dest0, dest0, tmp1); // dest0 is full ++ ++ __ srli_d(dest1, tmp2, 12); // 14-bit in dest1 ++ ++ __ ld_d(tmp1, Address(src, 3 * sizeof(jlong))); ++ __ slli_d(tmp1, tmp1, 14); ++ __ add_d(dest1, dest1, tmp1); // 40-bit in dest1 ++ ++ __ ld_d(tmp1, Address(src, 4 * sizeof(jlong))); ++ __ slli_d(tmp2, tmp1, 40); ++ __ add_d(dest1, dest1, tmp2); // dest1 is full ++ ++ if (dest2->is_valid()) { ++ __ srli_d(tmp1, tmp1, 24); ++ __ move(dest2, tmp1); // 2 bits in dest2 ++ } else { ++#ifdef ASSERT ++ Label OK; ++ __ srli_d(tmp1, tmp1, 24); ++ __ beq(R0, tmp1, OK); // 2 bits ++ __ stop("high bits of Poly1305 integer should be zero"); ++ __ should_not_reach_here(); ++ __ bind(OK); ++#endif ++ } ++ } ++ ++ // As above, but return only a 128-bit integer, packed into two ++ // 64-bit registers. ++ void poly1305_pack_26(Register dest0, Register dest1, Register src, Register tmp1, Register tmp2) { ++ poly1305_pack_26(dest0, dest1, noreg, src, tmp1, tmp2); ++ } ++ ++ // U_2:U_1:U_0: += (U_2 >> 2) * 5 ++ void poly1305_reduce(Register U_2, Register U_1, Register U_0, Register tmp1, Register tmp2) { ++ assert_different_registers(U_2, U_1, U_0, tmp1, tmp2); ++ ++ // First, U_2:U_1:U_0 += (U_2 >> 2) ++ __ srli_d(tmp1, U_2, 2); ++ __ cad(U_0, U_0, tmp1, tmp2); // Add tmp1 to U_0 with carry output to tmp2 ++ __ andi(U_2, U_2, right_2_bits); // Clear U_2 except for the lowest two bits ++ __ cad(U_1, U_1, tmp2, tmp2); // Add carry to U_1 with carry output to tmp2 ++ __ add_d(U_2, U_2, tmp2); ++ ++ // Second, U_2:U_1:U_0 += (U_2 >> 2) << 2 ++ __ slli_d(tmp1, tmp1, 2); ++ __ cad(U_0, U_0, tmp1, tmp2); // Add tmp1 to U_0 with carry output to tmp2 ++ __ cad(U_1, U_1, tmp2, tmp2); // Add carry to U_1 with carry output to tmp2 ++ __ add_d(U_2, U_2, tmp2); ++ } ++ ++ // Poly1305, RFC 7539 ++ // void com.sun.crypto.provider.Poly1305.processMultipleBlocks(byte[] input, int offset, int length, long[] aLimbs, long[] rLimbs) ++ ++ // Arguments: ++ // c_rarg0: input_start -- where the input is stored ++ // c_rarg1: length ++ // c_rarg2: acc_start -- where the output will be stored ++ // c_rarg3: r_start -- where the randomly generated 128-bit key is stored ++ ++ // See https://loup-vaillant.fr/tutorials/poly1305-design for a ++ // description of the tricks used to simplify and accelerate this ++ // computation. ++ ++ address generate_poly1305_processBlocks() { ++ __ align(CodeEntryAlignment); ++ StubCodeMark mark(this, "StubRoutines", "poly1305_processBlocks"); ++ address start = __ pc(); ++ __ enter(); ++ Label here; ++ ++ RegSet saved_regs = RegSet::of(S0); ++ RegSetIterator regs = (RegSet::range(A4, T8) - RegSet::of(SCR1, SCR2) + RegSet::of(S0)).begin(); ++ __ push(saved_regs); ++ ++ // Arguments ++ const Register input_start = c_rarg0, length = c_rarg1, acc_start = c_rarg2, r_start = c_rarg3; ++ ++ // R_n is the 128-bit randomly-generated key, packed into two ++ // registers. The caller passes this key to us as long[5], with ++ // BITS_PER_LIMB = 26. ++ const Register R_0 = *regs, R_1 = *++regs; ++ poly1305_pack_26(R_0, R_1, r_start, SCR1, SCR2); ++ ++ // RR_n is (R_n >> 2) * 5 ++ const Register RR_0 = *++regs, RR_1 = *++regs; ++ __ srli_d(SCR1, R_0, 2); ++ __ alsl_d(RR_0, SCR1, SCR1, 1); ++ __ srli_d(SCR1, R_1, 2); ++ __ alsl_d(RR_1, SCR1, SCR1, 1); ++ ++ // U_n is the current checksum ++ const Register U_0 = *++regs, U_1 = *++regs, U_2 = *++regs; ++ poly1305_pack_26(U_0, U_1, U_2, acc_start, SCR1, SCR2); ++ ++ static constexpr int BLOCK_LENGTH = 16; ++ Label DONE, LOOP; ++ ++ __ li(SCR1, BLOCK_LENGTH); ++ __ blt(length, SCR1, DONE); ++ ++ { ++ __ bind(LOOP); ++ ++ // S_n is to be the sum of U_n and the next block of data ++ const Register S_0 = *++regs, S_1 = *++regs, S_2 = *++regs; ++ __ ld_d(S_0, Address(input_start, 0)); ++ __ ld_d(S_1, Address(input_start, wordSize)); ++ ++ __ cad(S_0, S_0, U_0, SCR1); // Add U_0 to S_0 with carry output to SCR1 ++ __ cadc(S_1, S_1, U_1, SCR1); // Add U_1 with carry to S_1 with carry output to SCR1 ++ __ add_d(S_2, U_2, SCR1); ++ ++ __ addi_d(S_2, S_2, 1); ++ ++ const Register U_0HI = *++regs, U_1HI = *++regs; ++ ++ // NB: this logic depends on some of the special properties of ++ // Poly1305 keys. In particular, because we know that the top ++ // four bits of R_0 and R_1 are zero, we can add together ++ // partial products without any risk of needing to propagate a ++ // carry out. ++ __ wide_mul(U_0, U_0HI, S_0, R_0); ++ __ wide_madd(U_0, U_0HI, S_1, RR_1, SCR1, SCR2); ++ __ wide_madd(U_0, U_0HI, S_2, RR_0, SCR1, SCR2); ++ ++ __ wide_mul(U_1, U_1HI, S_0, R_1); ++ __ wide_madd(U_1, U_1HI, S_1, R_0, SCR1, SCR2); ++ __ wide_madd(U_1, U_1HI, S_2, RR_1, SCR1, SCR2); ++ ++ __ andi(U_2, R_0, right_2_bits); ++ __ mul_d(U_2, S_2, U_2); ++ ++ // Partial reduction mod 2**130 - 5 ++ __ cad(U_1, U_1, U_0HI, SCR1); // Add U_0HI to U_1 with carry output to SCR1 ++ __ adc(U_2, U_2, U_1HI, SCR1); ++ // Sum is now in U_2:U_1:U_0. ++ ++ // U_2:U_1:U_0: += (U_2 >> 2) * 5 ++ poly1305_reduce(U_2, U_1, U_0, SCR1, SCR2); ++ ++ __ addi_d(length, length, -BLOCK_LENGTH); ++ __ addi_d(input_start, input_start, BLOCK_LENGTH); ++ __ li(SCR1, BLOCK_LENGTH); ++ __ bge(length, SCR1, LOOP); ++ } ++ ++ // Further reduce modulo 2^130 - 5 ++ poly1305_reduce(U_2, U_1, U_0, SCR1, SCR2); ++ ++ // Unpack the sum into five 26-bit limbs and write to memory. ++ // First 26 bits is the first limb ++ __ slli_d(SCR1, U_0, 38); // Take lowest 26 bits ++ __ srli_d(SCR1, SCR1, 38); ++ __ st_d(SCR1, Address(acc_start)); // First 26-bit limb ++ ++ // 27-52 bits of U_0 is the second limb ++ __ slli_d(SCR1, U_0, 12); // Take next 27-52 bits ++ __ srli_d(SCR1, SCR1, 38); ++ __ st_d(SCR1, Address(acc_start, sizeof (jlong))); // Second 26-bit limb ++ ++ // Getting 53-64 bits of U_0 and 1-14 bits of U_1 in one register ++ __ srli_d(SCR1, U_0, 52); ++ __ slli_d(SCR2, U_1, 50); ++ __ srli_d(SCR2, SCR2, 38); ++ __ add_d(SCR1, SCR1, SCR2); ++ __ st_d(SCR1, Address(acc_start, 2 * sizeof (jlong))); // Third 26-bit limb ++ ++ // Storing 15-40 bits of U_1 ++ __ slli_d(SCR1, U_1, 24); // Already used up 14 bits ++ __ srli_d(SCR1, SCR1, 38); // Clear all other bits from SCR1 ++ __ st_d(SCR1, Address(acc_start, 3 * sizeof (jlong))); // Fourth 26-bit limb ++ ++ // Storing 41-64 bits of U_1 and first three bits from U_2 in one register ++ __ srli_d(SCR1, U_1, 40); ++ __ andi(SCR2, U_2, right_3_bits); ++ __ slli_d(SCR2, SCR2, 24); ++ __ add_d(SCR1, SCR1, SCR2); ++ __ st_d(SCR1, Address(acc_start, 4 * sizeof (jlong))); // Fifth 26-bit limb ++ ++ __ bind(DONE); ++ __ pop(saved_regs); ++ __ leave(); // Required for proper stackwalking ++ __ jr(RA); ++ ++ return start; ++ } ++ ++#endif // COMPILER2 ++ +#if INCLUDE_JFR + + // For c2: c_rarg0 is junk, call to runtime to write a checkpoint. @@ -61462,6 +61901,20 @@ index 00000000000..7a85b1fd838 + +#endif // INCLUDE_JFR + ++ // exception handler for upcall stubs ++ address generate_upcall_stub_exception_handler() { ++ StubCodeMark mark(this, "StubRoutines", "upcall stub exception handler"); ++ address start = __ pc(); ++ ++ // Native caller has no idea how to handle exceptions, ++ // so we just crash here. Up to callee to catch exceptions. ++ __ verify_oop(A0); // return a exception oop in a0 ++ __ call(CAST_FROM_FN_PTR(address, UpcallLinker::handle_uncaught_exception), relocInfo::runtime_call_type); ++ __ should_not_reach_here(); ++ ++ return start; ++ } ++ +#undef __ +#define __ masm-> + @@ -62197,8 +62650,10 @@ index 00000000000..7a85b1fd838 + + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm != nullptr) { -+ StubRoutines::la::_method_entry_barrier = generate_method_entry_barrier(); ++ StubRoutines::_method_entry_barrier = generate_method_entry_barrier(); + } ++ ++ StubRoutines::_upcall_stub_exception_handler = generate_upcall_stub_exception_handler(); + } + + void generate_compiler_stubs() { @@ -62222,6 +62677,10 @@ index 00000000000..7a85b1fd838 + StubRoutines::_montgomerySquare = g.generate_multiply(); + } + ++ if (UsePoly1305Intrinsics) { ++ StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks(); ++ } ++ + if (UseBigIntegerShiftIntrinsic) { + StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); + StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); @@ -62285,10 +62744,10 @@ index 00000000000..7a85b1fd838 +} diff --git a/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp b/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp new file mode 100644 -index 00000000000..56b7f34700d +index 00000000000..2494a0d8ab8 --- /dev/null +++ b/src/hotspot/cpu/loongarch/stubRoutines_loongarch.hpp -@@ -0,0 +1,90 @@ +@@ -0,0 +1,113 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -62343,12 +62802,19 @@ index 00000000000..56b7f34700d + // stack. The variable holds that location. + static address _vector_iota_indices; + static juint _crc_table[]; -+ static address _method_entry_barrier; + + static address _string_indexof_linear_ll; + static address _string_indexof_linear_uu; + static address _string_indexof_linear_ul; + ++ static address _jlong_fill; ++ static address _arrayof_jlong_fill; ++ ++ static julong _string_compress_index[]; ++ ++ static jfloat _round_float_imm[]; ++ static jdouble _round_double_imm[]; ++ + // begin trigonometric tables block. See comments in .cpp file + static juint _npio2_hw[]; + static jdouble _two_over_pi[]; @@ -62361,10 +62827,6 @@ index 00000000000..56b7f34700d + // Call back points for traps in compiled code + static address vector_iota_indices() { return _vector_iota_indices; } + -+ static address method_entry_barrier() { -+ return _method_entry_barrier; -+ } -+ + static address string_indexof_linear_ul() { + return _string_indexof_linear_ul; + } @@ -62376,15 +62838,35 @@ index 00000000000..56b7f34700d + static address string_indexof_linear_uu() { + return _string_indexof_linear_uu; + } ++ ++ static address jlong_fill() { ++ return _jlong_fill; ++ } ++ ++ static address arrayof_jlong_fill() { ++ return _arrayof_jlong_fill; ++ } ++ ++ static address string_compress_index() { ++ return (address) _string_compress_index; ++ } ++ ++ static address round_float_imm() { ++ return (address) _round_float_imm; ++ } ++ ++ static address round_double_imm() { ++ return (address) _round_double_imm; ++ } +}; + +#endif // CPU_LOONGARCH_STUBROUTINES_LOONGARCH_64_HPP diff --git a/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp b/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp new file mode 100644 -index 00000000000..e78cc503693 +index 00000000000..3cef08cb261 --- /dev/null +++ b/src/hotspot/cpu/loongarch/stubRoutines_loongarch_64.cpp -@@ -0,0 +1,182 @@ +@@ -0,0 +1,195 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -62419,11 +62901,12 @@ index 00000000000..e78cc503693 +// a description of how to extend it, see the stubRoutines.hpp file. + +//find the last fp value -+address StubRoutines::la::_method_entry_barrier = nullptr; +address StubRoutines::la::_vector_iota_indices = nullptr; +address StubRoutines::la::_string_indexof_linear_ll = nullptr; +address StubRoutines::la::_string_indexof_linear_uu = nullptr; +address StubRoutines::la::_string_indexof_linear_ul = nullptr; ++address StubRoutines::la::_jlong_fill = nullptr; ++address StubRoutines::la::_arrayof_jlong_fill = nullptr; + +/** + * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.5/crc32.h @@ -62536,6 +63019,10 @@ index 00000000000..e78cc503693 + -1.13596475577881948265e-11 // 0xBDA8FAE9BE8838D4 +}; + ++ATTRIBUTE_ALIGNED(128) julong StubRoutines::la::_string_compress_index[] = { ++ 0x0e0c0a0806040200UL, 0x1e1c1a1816141210UL // 128-bit shuffle index ++}; ++ +// Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi. +// Used in cases of very large argument. 396 hex digits is enough to support +// required precision. @@ -62567,12 +63054,20 @@ index 00000000000..e78cc503693 + 2.73370053816464559624e-44, // 0x36E3822280000000 + 2.16741683877804819444e-51, // 0x3569F31D00000000 +}; ++ ++ATTRIBUTE_ALIGNED(64) jfloat StubRoutines::la::_round_float_imm[] = { ++ -0.5f, 0.49999997f // magic number for ties ++}; ++ ++ATTRIBUTE_ALIGNED(64) jdouble StubRoutines::la::_round_double_imm[] = { ++ -0.5d, 0.49999999999999994d // magic number for ties ++}; diff --git a/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp new file mode 100644 -index 00000000000..d9419a9ce39 +index 00000000000..1d487c4e978 --- /dev/null +++ b/src/hotspot/cpu/loongarch/templateInterpreterGenerator_loongarch.cpp -@@ -0,0 +1,2106 @@ +@@ -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. @@ -62609,9 +63104,12 @@ index 00000000000..d9419a9ce39 +#include "interpreter/templateInterpreterGenerator.hpp" +#include "interpreter/templateTable.hpp" +#include "oops/arrayOop.hpp" -+#include "oops/methodData.hpp" +#include "oops/method.hpp" ++#include "oops/methodCounters.hpp" ++#include "oops/methodData.hpp" +#include "oops/oop.inline.hpp" ++#include "oops/resolvedIndyEntry.hpp" ++#include "oops/resolvedMethodEntry.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/arguments.hpp" @@ -63076,9 +63574,11 @@ index 00000000000..d9419a9ce39 +#ifdef ASSERT + { + Label L; -+ __ addi_d(T1, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); -+ __ sub_d(T1, T1, SP); // T1 = maximal sp for current fp -+ __ bge(T1, R0, L); // check if frame is complete ++ __ ld_d(T1, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ __ alsl_d(T1, T1, FP, LogBytesPerWord-1); ++ // maximal sp for current fp (stack grows negative) ++ // check if frame is complete ++ __ bge(T1, SP, L); + __ stop("interpreter frame not set up"); + __ bind(L); + } @@ -63142,7 +63642,8 @@ index 00000000000..d9419a9ce39 + address entry = __ pc(); + + // Restore stack bottom in case i2c adjusted stack -+ __ ld_d(SP, Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); ++ __ ld_d(AT, Address(FP, frame::interpreter_frame_last_sp_offset * wordSize)); ++ __ alsl_d(SP, AT, FP, LogBytesPerWord-1); + // and null it as marker that sp is now tos until next java call + __ st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); + @@ -63166,10 +63667,9 @@ index 00000000000..d9419a9ce39 + __ ld_hu(cache, Address(cache, in_bytes(ResolvedIndyEntry::num_parameters_offset()))); + __ alsl_d(SP, cache, SP, Interpreter::logStackElementSize - 1); + } else { -+ __ get_cache_and_index_at_bcp(cache, index, 1, index_size); -+ __ alsl_d(AT, index, cache, Address::times_ptr - 1); -+ __ ld_d(cache, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); -+ __ andi(cache, cache, ConstantPoolCacheEntry::parameter_size_mask); ++ assert(index_size == sizeof(u2), "Can only be u2"); ++ __ load_method_entry(cache, index); ++ __ ld_hu(cache, Address(cache, in_bytes(ResolvedMethodEntry::num_parameters_offset()))); + __ alsl_d(SP, cache, SP, Interpreter::logStackElementSize - 1); + } + @@ -63349,7 +63849,7 @@ index 00000000000..d9419a9ce39 + // generate_method_entry) so the guard should work for them too. + // + -+ const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; ++ const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); + + // total overhead size: entry_size + (saved fp thru expr stack bottom). + // be sure to change this if you add/subtract anything to/from the overhead area @@ -63416,7 +63916,7 @@ index 00000000000..d9419a9ce39 +// Rmethod - Method* +void TemplateInterpreterGenerator::lock_method(void) { + // synchronize method -+ const int entry_size = frame::interpreter_frame_monitor_size() * wordSize; ++ const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); + +#ifdef ASSERT + { Label L; @@ -63439,7 +63939,9 @@ index 00000000000..d9419a9ce39 + } + // add space for monitor & lock + __ addi_d(SP, SP, (-1) * entry_size); // add space for a monitor entry -+ __ st_d(SP, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ __ sub_d(AT, SP, FP); ++ __ srai_d(AT, AT, Interpreter::logStackElementSize); ++ __ st_d(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); + // set new monitor block top + __ st_d(T0, Address(SP, BasicObjectLock::obj_offset())); // store object + @@ -63501,7 +64003,8 @@ index 00000000000..d9419a9ce39 + } else { + __ st_d(BCP, FP, (-++i) * wordSize); // set bcp + } -+ __ st_d(SP, FP, (-++i) * wordSize); // reserve word for pointer to expression stack bottom ++ __ li(AT, frame::interpreter_frame_initial_sp_offset); ++ __ st_d(AT, FP, (-++i) * wordSize); // reserve word for pointer to expression stack bottom + assert(i == frame_size, "i should be equal to frame_size"); +} + @@ -63722,6 +64225,7 @@ index 00000000000..d9419a9ce39 + { + Label L; + __ ld_d(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ __ alsl_d(AT, AT, FP, LogBytesPerWord-1); + __ beq(AT, SP, L); + __ stop("broken stack frame setup in interpreter in asm"); + __ bind(L); @@ -64316,6 +64820,7 @@ index 00000000000..d9419a9ce39 + { + Label L; + __ ld_d(AT, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ __ alsl_d(AT, AT, FP, LogBytesPerWord-1); + __ beq(AT, SP, L); + __ stop("broken stack frame setup in interpreter in native"); + __ bind(L); @@ -64457,7 +64962,8 @@ index 00000000000..d9419a9ce39 + // fixup routine to move the mutated arguments onto the top of our + // expression stack if necessary. + __ move(T8, SP); -+ __ ld_d(A2, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ __ ld_d(AT, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ __ alsl_d(A2, AT, FP, LogBytesPerWord-1); + // PC must point into interpreter here + Label L; + __ bind(L); @@ -64465,7 +64971,8 @@ index 00000000000..d9419a9ce39 + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::popframe_move_outgoing_args), TREG, T8, A2); + __ reset_last_Java_frame(TREG, true); + // Restore the last_sp and null it out -+ __ ld_d(SP, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ __ ld_d(AT, FP, frame::interpreter_frame_last_sp_offset * wordSize); ++ __ alsl_d(SP, AT, FP, LogBytesPerWord-1); + __ st_d(R0, FP, frame::interpreter_frame_last_sp_offset * wordSize); + + @@ -64681,13 +65188,13 @@ index 00000000000..d9419a9ce39 +#endif // !PRODUCT diff --git a/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp b/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp new file mode 100644 -index 00000000000..ddb38faf446 +index 00000000000..9278dcfafc3 --- /dev/null +++ b/src/hotspot/cpu/loongarch/templateTable_loongarch.hpp -@@ -0,0 +1,43 @@ +@@ -0,0 +1,38 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2015, 2022, Loongson Technology. All rights reserved. ++ * 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 @@ -64713,12 +65220,7 @@ index 00000000000..ddb38faf446 +#ifndef CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP +#define CPU_LOONGARCH_TEMPLATETABLE_LOONGARCH_64_HPP + -+ static void prepare_invoke(int byte_no, -+ Register method, // linked method (or i-klass) -+ Register index = noreg, // itable index, MethodType, etc. -+ Register recv = noreg, // if caller wants to see it -+ Register flags = noreg // if caller wants to test it -+ ); ++ static void prepare_invoke(Register cache, Register recv); + static void invokevirtual_helper(Register index, Register recv, + Register flags); + static void volatile_barrier(); @@ -64730,10 +65232,10 @@ index 00000000000..ddb38faf446 +#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..fc459586dda +index 00000000000..74115edea62 --- /dev/null +++ b/src/hotspot/cpu/loongarch/templateTable_loongarch_64.cpp -@@ -0,0 +1,4009 @@ +@@ -0,0 +1,4077 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -64768,9 +65270,13 @@ index 00000000000..fc459586dda +#include "gc/shared/collectedHeap.hpp" +#include "memory/universe.hpp" +#include "oops/klass.inline.hpp" ++#include "oops/methodCounters.hpp" +#include "oops/methodData.hpp" +#include "oops/objArrayKlass.hpp" +#include "oops/oop.inline.hpp" ++#include "oops/resolvedFieldEntry.hpp" ++#include "oops/resolvedIndyEntry.hpp" ++#include "oops/resolvedMethodEntry.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/methodHandles.hpp" +#include "runtime/frame.inline.hpp" @@ -64879,9 +65385,18 @@ index 00000000000..fc459586dda + // additional, required work. + assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + assert(load_bc_into_bc_reg, "we use bc_reg as temp"); -+ __ get_cache_and_index_and_bytecode_at_bcp(tmp_reg, bc_reg, tmp_reg, byte_no, 1); ++ __ load_field_entry(tmp_reg, bc_reg); ++ if (byte_no == f1_byte) { ++ __ lea(tmp_reg, Address(tmp_reg, in_bytes(ResolvedFieldEntry::get_code_offset()))); ++ } else { ++ __ lea(tmp_reg, Address(tmp_reg, in_bytes(ResolvedFieldEntry::put_code_offset()))); ++ } ++ // Load-acquire the bytecode to match store-release in ResolvedFieldEntry::fill_in() ++ __ membar(MacroAssembler::AnyAny); ++ __ ld_bu(tmp_reg, Address(tmp_reg, 0)); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); + __ addi_d(bc_reg, R0, bc); -+ __ beq(tmp_reg, R0, L_patch_done); ++ __ beqz(tmp_reg, L_patch_done); + } + break; + default: @@ -65084,14 +65599,13 @@ index 00000000000..fc459586dda + __ get_vm_result_2(flags, TREG); + // VMr = obj = base address to find primitive value to push + // VMr2 = flags = (tos, off) using format of CPCE::_flags -+ __ li(AT, ConstantPoolCacheEntry::field_index_mask); ++ __ li(AT, ConstantPoolCache::field_index_mask); + __ andr(off, flags, AT); + __ add_d(obj, off, obj); + const Address field(obj, 0 * wordSize); + + // What sort of thing are we loading? -+ __ srli_d(flags, flags, ConstantPoolCacheEntry::tos_state_shift); -+ ConstantPoolCacheEntry::verify_tos_state_shift(); ++ __ srli_d(flags, flags, ConstantPoolCache::tos_state_shift); + + switch (bytecode()) { + case Bytecodes::_ldc: @@ -66869,6 +67383,19 @@ index 00000000000..fc459586dda + __ membar(__ StoreStore); + } + ++ 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())); ++ __ beqz(AT, no_safepoint); ++ __ push(state); ++ __ push_cont_fastpath(TREG); ++ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::at_safepoint)); ++ __ pop_cont_fastpath(TREG); ++ __ pop(state); ++ __ bind(no_safepoint); ++ } ++ + // Narrow result if state is itos but result type is smaller. + // Need to narrow in the return bytecode rather than in generate_return_entry + // since compiled code callers expect the result to already be narrowed. @@ -66887,24 +67414,30 @@ index 00000000000..fc459586dda +// the corresponding ConstantPoolCacheEntry +// used registers : T2 +// NOTE : the returned index need also shift left 4 to get the address! -+void TemplateTable::resolve_cache_and_index(int byte_no, ++void TemplateTable::resolve_cache_and_index_for_method(int byte_no, + Register Rcache, -+ Register index, -+ size_t index_size) { -+ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); ++ Register index) { + const Register temp = A1; -+ assert_different_registers(Rcache, index); ++ assert_different_registers(Rcache, index, temp); ++ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); + + Label resolved, clinit_barrier_slow; + + Bytecodes::Code code = bytecode(); -+ switch (code) { -+ case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break; -+ case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break; -+ default: break; -+ } + -+ __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size); ++ __ load_method_entry(Rcache, index); ++ switch(byte_no) { ++ case f1_byte: ++ __ lea(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::bytecode1_offset()))); ++ break; ++ case f2_byte: ++ __ lea(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::bytecode2_offset()))); ++ break; ++ } ++ // Load-acquire the bytecode to match store-release in InterpreterRuntime ++ __ membar(MacroAssembler::AnyAny); ++ __ ld_bu(temp, Address(temp, 0)); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); + // is resolved? + int i = (int)code; + __ addi_d(temp, temp, -i); @@ -66919,44 +67452,185 @@ index 00000000000..fc459586dda + __ call_VM(NOREG, entry, temp); + + // Update registers with resolved info -+ __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size); ++ __ load_method_entry(Rcache, index); + __ bind(resolved); + + // Class initialization barrier for static methods + if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) { -+ __ load_resolved_method_at_index(byte_no, temp, Rcache, index); ++ __ ld_d(temp, Address(Rcache, in_bytes(ResolvedMethodEntry::method_offset()))); + __ load_method_holder(temp, temp); + __ clinit_barrier(temp, AT, nullptr, &clinit_barrier_slow); + } +} +//END: LA + -+// The Rcache and index registers must be set before call -+void TemplateTable::load_field_cp_cache_entry(Register obj, ++void TemplateTable::resolve_cache_and_index_for_field(int byte_no, ++ Register Rcache, ++ Register index) { ++ const Register temp = SCR2; ++ assert_different_registers(Rcache, index, temp); ++ ++ Label resolved; ++ ++ Bytecodes::Code code = bytecode(); ++ switch (code) { ++ case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break; ++ case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break; ++ default: break; ++ } ++ ++ assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); ++ __ load_field_entry(Rcache, index); ++ if (byte_no == f1_byte) { ++ __ lea(temp, Address(Rcache, in_bytes(ResolvedFieldEntry::get_code_offset()))); ++ } else { ++ __ lea(temp, Address(Rcache, in_bytes(ResolvedFieldEntry::put_code_offset()))); ++ } ++ // Load-acquire the bytecode to match store-release in ResolvedFieldEntry::fill_in() ++ __ membar(MacroAssembler::AnyAny); ++ __ ld_bu(temp, Address(temp, 0)); ++ __ membar(Assembler::Membar_mask_bits(__ LoadLoad | __ LoadStore)); ++ __ li(AT, (int) code); // have we resolved this bytecode? ++ __ beq(temp, AT, resolved); ++ ++ // resolve first time through ++ address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache); ++ __ li(temp, (int) code); ++ __ call_VM(noreg, entry, temp); ++ ++ // Update registers with resolved info ++ __ load_field_entry(Rcache, index); ++ __ bind(resolved); ++} ++ ++void TemplateTable::load_resolved_field_entry(Register obj, + Register cache, -+ Register index, -+ Register off, ++ Register tos_state, ++ Register offset, + Register flags, + bool is_static = false) { -+ assert_different_registers(cache, index, flags, off); ++ assert_different_registers(cache, tos_state, flags, offset); + -+ ByteSize cp_base_offset = ConstantPoolCache::base_offset(); + // Field offset -+ __ alsl_d(AT, index, cache, Address::times_ptr - 1); -+ __ ld_d(off, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset())); ++ __ load_sized_value(offset, Address(cache, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); ++ + // Flags -+ __ ld_d(flags, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset())); ++ __ ld_bu(flags, Address(cache, in_bytes(ResolvedFieldEntry::flags_offset()))); + -+ // klass overwrite register ++ // TOS state ++ __ ld_bu(tos_state, Address(cache, in_bytes(ResolvedFieldEntry::type_offset()))); ++ ++ // Klass overwrite register + if (is_static) { -+ __ ld_d(obj, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset())); ++ __ ld_d(obj, Address(cache, ResolvedFieldEntry::field_holder_offset())); + const int mirror_offset = in_bytes(Klass::java_mirror_offset()); + __ ld_d(obj, Address(obj, mirror_offset)); -+ + __ resolve_oop_handle(obj, SCR2, SCR1); + } +} + ++void TemplateTable::load_resolved_method_entry_special_or_static(Register cache, ++ Register method, ++ Register flags) { ++ // setup registers ++ const Register index = flags; ++ assert_different_registers(method, cache, flags); ++ // determine constant pool cache field offsets ++ ++ resolve_cache_and_index_for_method(f1_byte, cache, index); ++ __ ld_bu(flags, Address(cache, in_bytes(ResolvedMethodEntry::flags_offset()))); ++ __ ld_d(method, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); ++} ++ ++void TemplateTable::load_resolved_method_entry_handle(Register cache, ++ Register method, ++ Register ref_index, ++ Register flags) { ++ // setup registers ++ const Register index = ref_index; ++ assert_different_registers(method, flags); ++ assert_different_registers(method, cache, index); ++ ++ // determine constant pool cache field offsets ++ resolve_cache_and_index_for_method(f1_byte, cache, index); ++ __ ld_bu(flags, Address(cache, in_bytes(ResolvedMethodEntry::flags_offset()))); ++ ++ // maybe push appendix to arguments (just before return address) ++ Label L_no_push; ++ __ andi(AT, flags, 1 << 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()))); ++ // Push the appendix as a trailing parameter. ++ // This must be done before we get the receiver, ++ // since the parameter_size includes it. ++ Register appendix = method; ++ __ load_resolved_reference_at_index(appendix, ref_index, T4); ++ __ push(appendix); // push appendix (MethodType, CallSite, etc.) ++ __ bind(L_no_push); ++ ++ __ ld_d(method, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); ++} ++ ++void TemplateTable::load_resolved_method_entry_interface(Register cache, ++ Register klass, ++ Register method_or_table_index, ++ Register flags) { ++ // setup registers ++ const Register index = method_or_table_index; ++ assert_different_registers(method_or_table_index, cache, flags); ++ ++ // determine constant pool cache field offsets ++ resolve_cache_and_index_for_method(f1_byte, cache, index); ++ __ ld_bu(flags, Address(cache, in_bytes(ResolvedMethodEntry::flags_offset()))); ++ ++ // Invokeinterface can behave in different ways: ++ // If calling a method from java.lang.Object, the forced virtual flag is true so the invocation will ++ // behave like an invokevirtual call. The state of the virtual final flag will determine whether a method or ++ // vtable index is placed in the register. ++ // 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); ++ __ beqz(AT, NotVirtual); ++ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ beqz(AT, NotVFinal); ++ __ ld_d(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); ++ __ b(Done); ++ ++ __ bind(NotVFinal); ++ __ ld_hu(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::table_index_offset()))); ++ __ b(Done); ++ ++ __ bind(NotVirtual); ++ __ ld_d(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); ++ __ ld_d(klass, Address(cache, in_bytes(ResolvedMethodEntry::klass_offset()))); ++ __ bind(Done); ++} ++ ++void TemplateTable::load_resolved_method_entry_virtual(Register cache, ++ Register method_or_table_index, ++ Register flags) { ++ // setup registers ++ const Register index = flags; ++ assert_different_registers(method_or_table_index, cache, flags); ++ ++ // determine constant pool cache field offsets ++ resolve_cache_and_index_for_method(f2_byte, cache, index); ++ __ ld_bu(flags, Address(cache, in_bytes(ResolvedMethodEntry::flags_offset()))); ++ ++ // 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); ++ __ beqz(AT, NotVFinal); ++ __ ld_d(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::method_offset()))); ++ __ b(Done); ++ ++ __ bind(NotVFinal); ++ __ ld_hu(method_or_table_index, Address(cache, in_bytes(ResolvedMethodEntry::table_index_offset()))); ++ __ bind(Done); ++} ++ +// The Rmethod register is input and overwritten to be the adapter method for the +// indy call. Return address (ra) is set to the return address for the adapter and +// an appendix may be pushed to the stack. Registers A2-A3 are clobbered. @@ -67025,46 +67699,6 @@ index 00000000000..fc459586dda + } +} + -+// get the method, itable_index and flags of the current invoke -+void TemplateTable::load_invoke_cp_cache_entry(int byte_no, -+ Register method, -+ Register itable_index, -+ Register flags, -+ bool is_invokevirtual, -+ bool is_invokevfinal, /*unused*/ -+ bool is_invokedynamic /*unused*/) { -+ // setup registers -+ const Register cache = T3; -+ const Register index = T1; -+ assert_different_registers(method, flags); -+ assert_different_registers(method, cache, index); -+ assert_different_registers(itable_index, flags); -+ assert_different_registers(itable_index, cache, index); -+ assert(is_invokevirtual == (byte_no == f2_byte), "is invokevirtual flag redundant"); -+ // determine constant pool cache field offsets -+ const int method_offset = in_bytes( -+ ConstantPoolCache::base_offset() + -+ ((byte_no == f2_byte) -+ ? ConstantPoolCacheEntry::f2_offset() -+ : ConstantPoolCacheEntry::f1_offset())); -+ const int flags_offset = in_bytes(ConstantPoolCache::base_offset() + -+ ConstantPoolCacheEntry::flags_offset()); -+ // access constant pool cache fields -+ const int index_offset = in_bytes(ConstantPoolCache::base_offset() + -+ ConstantPoolCacheEntry::f2_offset()); -+ -+ size_t index_size = sizeof(u2); -+ resolve_cache_and_index(byte_no, cache, index, index_size); -+ -+ __ alsl_d(AT, index, cache, Address::times_ptr - 1); -+ __ ld_d(method, AT, method_offset); -+ -+ if (itable_index != NOREG) { -+ __ ld_d(itable_index, AT, index_offset); -+ } -+ __ ld_d(flags, AT, flags_offset); -+} -+ +// The registers cache and index expected to be set before call. +// Correct values of the cache and index registers are preserved. +void TemplateTable::jvmti_post_field_access(Register cache, Register index, @@ -67083,13 +67717,9 @@ index 00000000000..fc459586dda + assert_different_registers(cache, index, AT); + __ li(AT, (intptr_t)JvmtiExport::get_field_access_count_addr()); + __ ld_w(AT, AT, 0); -+ __ beq(AT, R0, L1); -+ -+ __ get_cache_and_index_at_bcp(tmp2, tmp3, 1); ++ __ beqz(AT, L1); + -+ // cache entry pointer -+ __ addi_d(tmp2, tmp2, in_bytes(ConstantPoolCache::base_offset())); -+ __ alsl_d(tmp2, tmp3, tmp2, LogBytesPerWord - 1); ++ __ load_field_entry(tmp2, index); + + if (is_static) { + __ move(tmp1, R0); @@ -67102,7 +67732,7 @@ index 00000000000..fc459586dda + __ call_VM(NOREG, CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_access), + tmp1, tmp2); -+ __ get_cache_and_index_at_bcp(cache, index, 1); ++ __ load_field_entry(cache, index); + __ bind(L1); + } +} @@ -67133,21 +67763,21 @@ index 00000000000..fc459586dda +void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) { + transition(vtos, vtos); + -+ const Register cache = T3; -+ const Register index = T0; -+ -+ const Register obj = T3; -+ const Register off = T2; -+ const Register flags = T1; ++ const Register cache = T3; ++ const Register index = T0; ++ const Register obj = T3; ++ const Register off = T2; ++ const Register flags = T1; ++ const Register tos_state = T0; + + const Register scratch = T8; + -+ resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); ++ resolve_cache_and_index_for_field(byte_no, cache, index); + jvmti_post_field_access(cache, index, is_static, false); -+ load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); ++ load_resolved_field_entry(obj, cache, tos_state, off, flags, is_static); + + { -+ __ li(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift); ++ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); + __ andr(scratch, scratch, flags); + + Label notVolatile; @@ -67157,17 +67787,14 @@ index 00000000000..fc459586dda + } + + if (!is_static) pop_and_check_object(obj); -+ __ add_d(index, obj, off); + -+ const Address field(index, 0); ++ const Address field(obj, off); + + Label Done, notByte, notBool, notInt, notShort, notChar, + notLong, notFloat, notObj, notDouble; + + assert(btos == 0, "change code, btos != 0"); -+ __ srli_d(flags, flags, ConstantPoolCacheEntry::tos_state_shift); -+ __ andi(flags, flags, ConstantPoolCacheEntry::tos_state_mask); -+ __ bne(flags, R0, notByte); ++ __ bnez(tos_state, notByte); + + // btos + __ access_load_at(T_BYTE, IN_HEAP, FSR, field, noreg, noreg); @@ -67182,7 +67809,7 @@ index 00000000000..fc459586dda + + __ bind(notByte); + __ li(AT, ztos); -+ __ bne(flags, AT, notBool); ++ __ bne(tos_state, AT, notBool); + + // ztos + __ access_load_at(T_BOOLEAN, IN_HEAP, FSR, field, noreg, noreg); @@ -67197,7 +67824,7 @@ index 00000000000..fc459586dda + + __ bind(notBool); + __ li(AT, itos); -+ __ bne(flags, AT, notInt); ++ __ bne(tos_state, AT, notInt); + + // itos + __ access_load_at(T_INT, IN_HEAP, FSR, field, noreg, noreg); @@ -67211,11 +67838,11 @@ index 00000000000..fc459586dda + + __ bind(notInt); + __ li(AT, atos); -+ __ bne(flags, AT, notObj); ++ __ bne(tos_state, AT, notObj); + + // atos + //add for compressedoops -+ do_oop_load(_masm, Address(index, 0), FSR, IN_HEAP); ++ do_oop_load(_masm, field, FSR, IN_HEAP); + __ push(atos); + + if (!is_static && rc == may_rewrite) { @@ -67225,7 +67852,7 @@ index 00000000000..fc459586dda + + __ bind(notObj); + __ li(AT, ctos); -+ __ bne(flags, AT, notChar); ++ __ bne(tos_state, AT, notChar); + + // ctos + __ access_load_at(T_CHAR, IN_HEAP, FSR, field, noreg, noreg); @@ -67238,7 +67865,7 @@ index 00000000000..fc459586dda + + __ bind(notChar); + __ li(AT, stos); -+ __ bne(flags, AT, notShort); ++ __ bne(tos_state, AT, notShort); + + // stos + __ access_load_at(T_SHORT, IN_HEAP, FSR, field, noreg, noreg); @@ -67251,7 +67878,7 @@ index 00000000000..fc459586dda + + __ bind(notShort); + __ li(AT, ltos); -+ __ bne(flags, AT, notLong); ++ __ bne(tos_state, AT, notLong); + + // ltos + __ access_load_at(T_LONG, IN_HEAP | MO_RELAXED, FSR, field, noreg, noreg); @@ -67262,7 +67889,7 @@ index 00000000000..fc459586dda + + __ bind(notLong); + __ li(AT, ftos); -+ __ bne(flags, AT, notFloat); ++ __ bne(tos_state, AT, notFloat); + + // ftos + __ access_load_at(T_FLOAT, IN_HEAP, noreg /* ftos */, field, noreg, noreg); @@ -67276,7 +67903,7 @@ index 00000000000..fc459586dda + __ bind(notFloat); + __ li(AT, dtos); +#ifdef ASSERT -+ __ bne(flags, AT, notDouble); ++ __ bne(tos_state, AT, notDouble); +#endif + + // dtos @@ -67320,8 +67947,6 @@ index 00000000000..fc459586dda +void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) { + transition(vtos, vtos); + -+ ByteSize cp_base_offset = ConstantPoolCache::base_offset(); -+ + if (JvmtiExport::can_post_field_modification()) { + // Check to see if a field modification watch has been set before + // we take the time to call into the VM. @@ -67330,14 +67955,12 @@ index 00000000000..fc459586dda + Register tmp1 = T2; + Register tmp2 = T1; + Register tmp3 = T3; -+ Register tmp4 = T4; -+ assert_different_registers(cache, index, tmp4); + + __ li(AT, JvmtiExport::get_field_modification_count_addr()); + __ ld_w(AT, AT, 0); -+ __ beq(AT, R0, L1); ++ __ beqz(AT, L1); + -+ __ get_cache_and_index_at_bcp(tmp2, tmp4, 1); ++ __ move(tmp2, cache); + + if (is_static) { + __ move(tmp1, R0); @@ -67346,13 +67969,8 @@ index 00000000000..fc459586dda + // the object. We don't know the size of the value, though; it + // could be one or two words depending on its type. As a result, + // we must find the type to determine where the object is. ++ __ ld_bu(tmp3, Address(tmp2, in_bytes(ResolvedFieldEntry::type_offset()))); + Label two_word, valsize_known; -+ __ alsl_d(AT, tmp4, tmp2, Address::times_8 - 1); -+ __ ld_wu(tmp3, AT, in_bytes(cp_base_offset + -+ ConstantPoolCacheEntry::flags_offset())); -+ __ srli_d(tmp3, tmp3, ConstantPoolCacheEntry::tos_state_shift); -+ -+ ConstantPoolCacheEntry::verify_tos_state_shift(); + __ move(tmp1, SP); + __ li(AT, ltos); + __ beq(tmp3, AT, two_word); @@ -67368,9 +67986,6 @@ index 00000000000..fc459586dda + // setup object pointer + __ ld_d(tmp1, tmp1, 0 * wordSize); + } -+ // cache entry pointer -+ __ addi_d(tmp2, tmp2, in_bytes(cp_base_offset)); -+ __ alsl_d(tmp2, tmp4, tmp2, LogBytesPerWord - 1); + // object (tos) + __ move(tmp3, SP); + // tmp1: object pointer set up above (null if static) @@ -67380,7 +67995,7 @@ index 00000000000..fc459586dda + CAST_FROM_FN_PTR(address, + InterpreterRuntime::post_field_modification), + tmp1, tmp2, tmp3); -+ __ get_cache_and_index_at_bcp(cache, index, 1); ++ __ load_field_entry(cache, index); + __ bind(L1); + } +} @@ -67394,22 +68009,23 @@ index 00000000000..fc459586dda +void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) { + transition(vtos, vtos); + -+ const Register cache = T3; -+ const Register index = T0; -+ const Register obj = T3; -+ const Register off = T2; -+ const Register flags = T1; -+ const Register bc = T3; ++ const Register cache = T3; ++ const Register index = T0; ++ const Register tos_state = T0; ++ const Register obj = T3; ++ const Register off = T2; ++ const Register flags = T1; ++ const Register bc = T3; + + const Register scratch = T8; + -+ resolve_cache_and_index(byte_no, cache, index, sizeof(u2)); ++ resolve_cache_and_index_for_field(byte_no, cache, index); + jvmti_post_field_mod(cache, index, is_static); -+ load_field_cp_cache_entry(obj, cache, index, off, flags, is_static); ++ load_resolved_field_entry(obj, cache, tos_state, off, flags, is_static); + + Label Done; + { -+ __ li(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift); ++ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); + __ andr(scratch, scratch, flags); + + Label notVolatile; @@ -67424,9 +68040,7 @@ index 00000000000..fc459586dda + assert(btos == 0, "change code, btos != 0"); + + // btos -+ __ srli_d(flags, flags, ConstantPoolCacheEntry::tos_state_shift); -+ __ andi(flags, flags, ConstantPoolCacheEntry::tos_state_mask); -+ __ bne(flags, R0, notByte); ++ __ bnez(tos_state, notByte); + + __ pop(btos); + if (!is_static) { @@ -67443,7 +68057,7 @@ index 00000000000..fc459586dda + // ztos + __ bind(notByte); + __ li(AT, ztos); -+ __ bne(flags, AT, notBool); ++ __ bne(tos_state, AT, notBool); + + __ pop(ztos); + if (!is_static) { @@ -67461,7 +68075,7 @@ index 00000000000..fc459586dda + // itos + __ bind(notBool); + __ li(AT, itos); -+ __ bne(flags, AT, notInt); ++ __ bne(tos_state, AT, notInt); + + __ pop(itos); + if (!is_static) { @@ -67478,7 +68092,7 @@ index 00000000000..fc459586dda + // atos + __ bind(notInt); + __ li(AT, atos); -+ __ bne(flags, AT, notObj); ++ __ bne(tos_state, AT, notObj); + + __ pop(atos); + if (!is_static) { @@ -67495,7 +68109,7 @@ index 00000000000..fc459586dda + // ctos + __ bind(notObj); + __ li(AT, ctos); -+ __ bne(flags, AT, notChar); ++ __ bne(tos_state, AT, notChar); + + __ pop(ctos); + if (!is_static) { @@ -67511,7 +68125,7 @@ index 00000000000..fc459586dda + // stos + __ bind(notChar); + __ li(AT, stos); -+ __ bne(flags, AT, notShort); ++ __ bne(tos_state, AT, notShort); + + __ pop(stos); + if (!is_static) { @@ -67527,7 +68141,7 @@ index 00000000000..fc459586dda + // ltos + __ bind(notShort); + __ li(AT, ltos); -+ __ bne(flags, AT, notLong); ++ __ bne(tos_state, AT, notLong); + + __ pop(ltos); + if (!is_static) { @@ -67543,7 +68157,7 @@ index 00000000000..fc459586dda + // ftos + __ bind(notLong); + __ li(AT, ftos); -+ __ bne(flags, AT, notFloat); ++ __ bne(tos_state, AT, notFloat); + + __ pop(ftos); + if (!is_static) { @@ -67561,7 +68175,7 @@ index 00000000000..fc459586dda + __ bind(notFloat); + __ li(AT, dtos); +#ifdef ASSERT -+ __ bne(flags, AT, notDouble); ++ __ bne(tos_state, AT, notDouble); +#endif + + __ pop(dtos); @@ -67637,7 +68251,7 @@ index 00000000000..fc459586dda + } + __ move(tmp3, SP); + // access constant pool cache entry -+ __ get_cache_entry_pointer_at_bcp(tmp2, FSR, 1); ++ __ load_field_entry(tmp2, FSR); + __ verify_oop(tmp1); + // tmp1: object pointer copied above + // tmp2: cache entry pointer @@ -67677,21 +68291,18 @@ index 00000000000..fc459586dda + jvmti_post_fast_field_mod(); + + // access constant pool cache -+ __ get_cache_and_index_at_bcp(T3, T2, 1); ++ __ load_field_entry(T3, T2); + + // Must prevent reordering of the following cp cache loads with bytecode load + __ membar(__ LoadLoad); -+ -+ // test for volatile with T1 -+ __ alsl_d(AT, T2, T3, Address::times_8 - 1); -+ __ ld_d(T1, AT, in_bytes(base + ConstantPoolCacheEntry::flags_offset())); -+ -+ // replace index with field offset from cache entry -+ __ ld_d(T2, AT, in_bytes(base + ConstantPoolCacheEntry::f2_offset())); ++ __ push(T0); ++ // T2: field offset, T0: TOS, T1: flags ++ load_resolved_field_entry(T3, T3, T0, T2, T1); ++ __ pop(T0); + + Label Done; + { -+ __ li(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift); ++ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); + __ andr(scratch, scratch, T1); + + Label notVolatile; @@ -67767,7 +68378,7 @@ index 00000000000..fc459586dda + __ ld_w(T3, AT, 0); + __ beq(T3, R0, L1); + // access constant pool cache entry -+ __ get_cache_entry_pointer_at_bcp(T3, T1, 1); ++ __ load_field_entry(T3, T1); + __ move(TSR, FSR); + __ verify_oop(FSR); + // FSR: object pointer copied above @@ -67780,22 +68391,21 @@ index 00000000000..fc459586dda + } + + // access constant pool cache -+ __ get_cache_and_index_at_bcp(T3, T2, 1); ++ __ 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 -+ __ alsl_d(AT, T2, T3, Address::times_8 - 1); -+ __ ld_d(T2, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); ++ __ 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()))); + + { -+ __ ld_d(AT, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); -+ __ li(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift); -+ __ andr(scratch, scratch, AT); ++ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); ++ __ andr(scratch, scratch, T1); + + Label notVolatile; -+ __ beq(scratch, R0, notVolatile); ++ __ beqz(scratch, notVolatile); + __ membar(MacroAssembler::AnyAny); + __ bind(notVolatile); + } @@ -67859,13 +68469,12 @@ index 00000000000..fc459586dda + // get receiver + __ ld_d(T1, aaddress(0)); + // access constant pool cache -+ __ get_cache_and_index_at_bcp(T3, T2, 2); -+ __ alsl_d(AT, T2, T3, Address::times_8 - 1); -+ __ ld_d(T2, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())); ++ __ load_field_entry(T3, T2, 2); ++ __ load_sized_value(T2, Address(T3, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + + { -+ __ ld_d(AT, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); -+ __ li(scratch, 1 << ConstantPoolCacheEntry::is_volatile_shift); ++ __ ld_bu(AT, Address(T3, in_bytes(ResolvedFieldEntry::flags_offset()))); ++ __ li(scratch, 1 << ResolvedFieldEntry::is_volatile_shift); + __ andr(scratch, scratch, AT); + + Label notVolatile; @@ -67904,91 +68513,33 @@ index 00000000000..fc459586dda +//----------------------------------------------------------------------------- +// Calls + -+// method, index, recv, flags: T1, T2, T3, T1 -+// byte_no = 2 for _invokevirtual, 1 else -+// T0 : return address -+// get the method & index of the invoke, and push the return address of -+// the invoke(first word in the frame) -+// this address is where the return code jmp to. -+// NOTE : this method will set T3&T1 as recv&flags -+void TemplateTable::prepare_invoke(int byte_no, -+ Register method, // linked method (or i-klass) -+ Register index, // itable index, MethodType, etc. -+ Register recv, // if caller wants to see it -+ Register flags // if caller wants to test it -+ ) { -+ // determine flags -+ const Bytecodes::Code code = bytecode(); -+ const bool is_invokeinterface = code == Bytecodes::_invokeinterface; -+ const bool is_invokedynamic = code == Bytecodes::_invokedynamic; -+ const bool is_invokehandle = code == Bytecodes::_invokehandle; -+ const bool is_invokevirtual = code == Bytecodes::_invokevirtual; -+ const bool is_invokespecial = code == Bytecodes::_invokespecial; -+ const bool load_receiver = (recv != noreg); -+ const bool save_flags = (flags != noreg); -+ assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic),""); -+ assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal"); -+ assert(flags == noreg || flags == T1, "error flags reg."); -+ assert(recv == noreg || recv == T3, "error recv reg."); -+ -+ // setup registers & access constant pool cache -+ if(recv == noreg) recv = T3; -+ if(flags == noreg) flags = T1; -+ assert_different_registers(method, index, recv, flags); ++void TemplateTable::prepare_invoke(Register cache, Register recv) { ++ ++ Bytecodes::Code code = bytecode(); ++ const bool load_receiver = (code != Bytecodes::_invokestatic) && (code != Bytecodes::_invokedynamic); + + // save 'interpreter return address' + __ save_bcp(); + -+ load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic); -+ -+ if (is_invokehandle) { -+ Label L_no_push; -+ __ li(AT, (1 << ConstantPoolCacheEntry::has_appendix_shift)); -+ __ andr(AT, AT, flags); -+ __ beq(AT, R0, L_no_push); -+ // Push the appendix as a trailing parameter. -+ // This must be done before we get the receiver, -+ // since the parameter_size includes it. -+ Register tmp = T6; -+ __ push(tmp); -+ __ move(tmp, index); -+ __ load_resolved_reference_at_index(index, tmp, recv); -+ __ pop(tmp); -+ __ push(index); // push appendix (MethodType, CallSite, etc.) -+ __ bind(L_no_push); -+ } ++ // Load TOS state for later ++ __ ld_bu(T8, Address(cache, in_bytes(ResolvedMethodEntry::type_offset()))); + + // load receiver if needed (note: no return address pushed yet) + if (load_receiver) { -+ // parameter_size_mask = 1 << 8 -+ __ andi(recv, flags, ConstantPoolCacheEntry::parameter_size_mask); ++ __ ld_hu(recv, Address(cache, in_bytes(ResolvedMethodEntry::num_parameters_offset()))); + + Address recv_addr = __ argument_address(recv, -1); + __ ld_d(recv, recv_addr); + __ verify_oop(recv); + } -+ if(save_flags) { -+ __ move(BCP, flags); -+ } -+ -+ // compute return type -+ __ srli_d(flags, flags, ConstantPoolCacheEntry::tos_state_shift); -+ __ andi(flags, flags, 0xf); + -+ // Make sure we don't need to mask flags for tos_state_shift after the above shift -+ ConstantPoolCacheEntry::verify_tos_state_shift(); + // load return address + { + const address table = (address) Interpreter::invoke_return_entry_table_for(code); + __ li(AT, (long)table); -+ __ alsl_d(AT, flags, AT, LogBytesPerWord - 1); ++ __ alsl_d(AT, T8, AT, LogBytesPerWord - 1); + __ ld_d(RA, AT, 0); + } -+ -+ if (save_flags) { -+ __ move(flags, BCP); -+ __ restore_bcp(); -+ } +} + +// used registers : T0, T3, T1, T2 @@ -68003,8 +68554,7 @@ index 00000000000..fc459586dda + + // Test for an invoke of a final method + Label notFinal; -+ __ li(AT, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); -+ __ andr(AT, flags, AT); ++ __ andi(AT, flags, 1 << ResolvedMethodEntry::is_vfinal_shift); + __ beq(AT, R0, notFinal); + + Register method = index; // method must be Rmethod @@ -68045,7 +68595,10 @@ index 00000000000..fc459586dda +void TemplateTable::invokevirtual(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f2_byte, "use this argument"); -+ prepare_invoke(byte_no, Rmethod, NOREG, T3, T1); ++ load_resolved_method_entry_virtual(T3, // ResolvedMethodEntry* ++ Rmethod, // Method* or itable index ++ T1); // flags ++ prepare_invoke(T3, T3); // recv + // now recv & flags in T3, T1 + invokevirtual_helper(Rmethod, T3, T1); +} @@ -68055,7 +68608,11 @@ index 00000000000..fc459586dda +void TemplateTable::invokespecial(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); -+ prepare_invoke(byte_no, Rmethod, NOREG, T3); ++ ++ load_resolved_method_entry_special_or_static(T3, // ResolvedMethodEntry* ++ Rmethod, // Method* ++ T1); // flags ++ prepare_invoke(T3, T3); // get receiver also for null check + // now recv & flags in T3, T1 + __ verify_oop(T3); + __ null_check(T3); @@ -68074,7 +68631,11 @@ index 00000000000..fc459586dda +void TemplateTable::invokestatic(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); -+ prepare_invoke(byte_no, Rmethod, NOREG); ++ ++ load_resolved_method_entry_special_or_static(T3, // ResolvedMethodEntry* ++ Rmethod, // Method* ++ T1); // flags ++ prepare_invoke(T3, T3); // get receiver also for null check + + __ profile_call(T4); + @@ -68104,7 +68665,13 @@ index 00000000000..fc459586dda + transition(vtos, vtos); + //this method will use T1-T4 and T0 + assert(byte_no == f1_byte, "use this argument"); -+ prepare_invoke(byte_no, T2, Rmethod, T3, T1); ++ ++ load_resolved_method_entry_interface(T3, // ResolvedMethodEntry* ++ T2, // Klass* ++ Rmethod, // Method* or itable/vtable index ++ T1); // flags ++ prepare_invoke(T3, T3); // receiver ++ + // T2: reference klass (from f1) if interface method + // Rmethod: method (from f2) + // T3: receiver @@ -68116,9 +68683,8 @@ index 00000000000..fc459586dda + // Special case of invokeinterface called for virtual method of + // java.lang.Object. See cpCache.cpp for details. + Label notObjectMethod; -+ __ li(AT, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift)); -+ __ andr(AT, T1, AT); -+ __ beq(AT, R0, notObjectMethod); ++ __ andi(AT, T1, 1 << ResolvedMethodEntry::is_forced_virtual_shift); ++ __ beqz(AT, notObjectMethod); + + invokevirtual_helper(Rmethod, T3, T1); + // no return from above @@ -68129,9 +68695,8 @@ index 00000000000..fc459586dda + + // Check for private method invocation - indicated by vfinal + Label notVFinal; -+ __ li(AT, (1 << ConstantPoolCacheEntry::is_vfinal_shift)); -+ __ andr(AT, T1, AT); -+ __ beq(AT, R0, notVFinal); ++ __ andi(AT, T1, 1 << ResolvedMethodEntry::is_vfinal_shift); ++ __ beqz(AT, notVFinal); + + // Get receiver klass into FSR + __ load_klass(FSR, T3); @@ -68212,7 +68777,6 @@ index 00000000000..fc459586dda + + __ bind(no_such_method); + // throw exception -+ __ pop(Rmethod); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); + __ restore_locals(); + // Pass arguments for generating a verbose error message. @@ -68226,7 +68790,6 @@ index 00000000000..fc459586dda + + __ bind(no_such_interface); + // throw exception -+ __ pop(Rmethod); // pop return address (pushed by prepare_invoke) + __ restore_bcp(); + __ restore_locals(); + // Pass arguments for generating a verbose error message. @@ -68240,30 +68803,32 @@ index 00000000000..fc459586dda +void TemplateTable::invokehandle(int byte_no) { + transition(vtos, vtos); + assert(byte_no == f1_byte, "use this argument"); -+ const Register T2_method = Rmethod; -+ const Register FSR_mtype = FSR; -+ const Register T3_recv = T3; + -+ prepare_invoke(byte_no, T2_method, FSR_mtype, T3_recv); -+ //??__ verify_method_ptr(T2_method); -+ __ verify_oop(T3_recv); -+ __ null_check(T3_recv); ++ load_resolved_method_entry_handle(T3, // ResolvedMethodEntry* ++ Rmethod, // Method* ++ T2, // Resolved reference ++ T1); // flags ++ prepare_invoke(T3, T3); ++ ++ //??__ verify_method_ptr(T2_method); ++ __ verify_oop(T3); ++ __ null_check(T3); + -+ // T4: MethodType object (from cpool->resolved_references[f1], if necessary) -+ // T2_method: MH.invokeExact_MT method (from f2) ++ // T4: MethodType object (from cpool->resolved_references[f1], if necessary) ++ // T2_method: MH.invokeExact_MT method (from f2) + -+ // Note: T4 is already pushed (if necessary) by prepare_invoke ++ // Note: T4 is already pushed (if necessary) by prepare_invoke + -+ // FIXME: profile the LambdaForm also -+ __ profile_final_call(T4); ++ // FIXME: profile the LambdaForm also ++ __ profile_final_call(T4); + -+ // T8: tmp, used for mdp -+ // T2_method: callee -+ // T4: tmp -+ // is_virtual: true -+ __ profile_arguments_type(T8, T2_method, T4, true); ++ // T8: tmp, used for mdp ++ // T2_method: callee ++ // T4: tmp ++ // is_virtual: true ++ __ profile_arguments_type(T8, Rmethod, T4, true); + -+ __ jump_from_interpreted(T2_method); ++ __ jump_from_interpreted(Rmethod); +} + +void TemplateTable::invokedynamic(int byte_no) { @@ -68275,9 +68840,9 @@ index 00000000000..fc459586dda + load_invokedynamic_entry(Rmethod); + + // T2: CallSite object (from cpool->resolved_references[f1]) -+ // Rmethod: MH.linkToCallSite method (from f2) ++ // Rmethod: MH.linkToCallSite method + -+ // Note: T2_callsite is already pushed by prepare_invoke ++ // Note: T2_callsite is already pushed + // %%% should make a type profile for any invokedynamic that takes a ref argument + // profile this call + __ profile_call(T4); @@ -68610,7 +69175,7 @@ index 00000000000..fc459586dda + + const Address monitor_block_top(FP, frame::interpreter_frame_monitor_block_top_offset + * wordSize); -+ const int entry_size = (frame::interpreter_frame_monitor_size()* wordSize); ++ const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); + Label allocated; + + const Register monitor_reg = T0; @@ -68622,6 +69187,7 @@ index 00000000000..fc459586dda + { + Label entry, loop, exit, next; + __ ld_d(T2, monitor_block_top); ++ __ alsl_d(T2, T2, FP, LogBytesPerWord-1); + __ addi_d(T3, FP, frame::interpreter_frame_initial_sp_offset * wordSize); + __ b(entry); + @@ -68647,9 +69213,12 @@ index 00000000000..fc459586dda + Label entry, loop; + // 1. compute new pointers // SP: old expression stack top + __ ld_d(monitor_reg, monitor_block_top); ++ __ alsl_d(monitor_reg, monitor_reg, FP, LogBytesPerWord-1); + __ addi_d(SP, SP, -entry_size); + __ addi_d(monitor_reg, monitor_reg, -entry_size); -+ __ st_d(monitor_reg, monitor_block_top); ++ __ sub_d(AT, monitor_reg, FP); ++ __ srai_d(AT, AT, Interpreter::logStackElementSize); ++ __ st_d(AT, monitor_block_top); + __ move(T3, SP); + __ b(entry); + @@ -68685,7 +69254,7 @@ index 00000000000..fc459586dda + + __ null_check(FSR); + -+ const int entry_size =(frame::interpreter_frame_monitor_size()* wordSize); ++ const int entry_size = frame::interpreter_frame_monitor_size_in_bytes(); + + const Register monitor_top = T0; + const Register monitor_bot = T2; @@ -68696,6 +69265,7 @@ index 00000000000..fc459586dda + { + Label entry, loop; + __ ld_d(monitor_top, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize); ++ __ alsl_d(monitor_top, monitor_top, FP, LogBytesPerWord-1); + __ addi_d(monitor_bot, FP, frame::interpreter_frame_initial_sp_offset * wordSize); + __ b(entry); + @@ -68745,10 +69315,10 @@ index 00000000000..fc459586dda +} 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..ccaa16bb6b1 +index 00000000000..19491e55251 --- /dev/null +++ b/src/hotspot/cpu/loongarch/upcallLinker_loongarch_64.cpp -@@ -0,0 +1,347 @@ +@@ -0,0 +1,341 @@ +/* + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2021, 2023, Loongson Technology. All rights reserved. @@ -68868,7 +69438,6 @@ index 00000000000..ccaa16bb6b1 +static const int upcall_stub_size_per_arg = 16; + +address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, -+ BasicType* in_sig_bt, int total_in_args, + BasicType* out_sig_bt, int total_out_args, + BasicType ret_type, + jobject jabi, jobject jconv, @@ -68876,26 +69445,18 @@ index 00000000000..ccaa16bb6b1 + ResourceMark rm; + const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi); + const CallRegs call_regs = ForeignGlobals::parse_call_regs(jconv); -+ int code_size = upcall_stub_code_base_size + (total_in_args * upcall_stub_size_per_arg); ++ int code_size = upcall_stub_code_base_size + (total_out_args * upcall_stub_size_per_arg); + CodeBuffer buffer("upcall_stub", code_size, /* locs_size = */ 1); ++ if (buffer.blob() == nullptr) { ++ return nullptr; ++ } + -+ Register shuffle_reg = S0; -+ JavaCallingConvention out_conv; -+ NativeCallingConvention in_conv(call_regs._arg_regs); -+ ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, as_VMStorage(shuffle_reg)); ++ GrowableArray unfiltered_out_regs; ++ int out_arg_bytes = ForeignGlobals::java_calling_convention(out_sig_bt, total_out_args, unfiltered_out_regs); + int preserved_bytes = SharedRuntime::out_preserve_stack_slots() * VMRegImpl::stack_slot_size; -+ int stack_bytes = preserved_bytes + arg_shuffle.out_arg_bytes(); ++ int stack_bytes = preserved_bytes + out_arg_bytes; + int out_arg_area = align_up(stack_bytes, StackAlignmentInBytes); + -+#ifndef PRODUCT -+ LogTarget(Trace, foreign, upcall) lt; -+ if (lt.is_enabled()) { -+ ResourceMark rm; -+ LogStream ls(lt); -+ arg_shuffle.print_on(&ls); -+ } -+#endif -+ + // out_arg_area (for stack arguments) doubles as shadow space for native calls. + // make sure it is big enough. + if (out_arg_area < frame::arg_reg_save_area_bytes) { @@ -68903,13 +69464,13 @@ index 00000000000..ccaa16bb6b1 + } + + int reg_save_area_size = compute_reg_save_area_size(abi); -+ RegSpiller arg_spilller(call_regs._arg_regs); ++ RegSpiller arg_spiller(call_regs._arg_regs); + RegSpiller result_spiller(call_regs._ret_regs); + + int shuffle_area_offset = 0; + int res_save_area_offset = shuffle_area_offset + out_arg_area; + int arg_save_area_offset = res_save_area_offset + result_spiller.spill_size_bytes(); -+ int reg_save_area_offset = arg_save_area_offset + arg_spilller.spill_size_bytes(); ++ int reg_save_area_offset = arg_save_area_offset + arg_spiller.spill_size_bytes(); + int frame_data_offset = reg_save_area_offset + reg_save_area_size; + int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData); + @@ -68923,6 +69484,20 @@ index 00000000000..ccaa16bb6b1 + locs.set(StubLocations::RETURN_BUFFER, abi._scratch1); + } + ++ Register shuffle_reg = S0; ++ GrowableArray in_regs = ForeignGlobals::replace_place_holders(call_regs._arg_regs, locs); ++ GrowableArray filtered_out_regs = ForeignGlobals::upcall_filter_receiver_reg(unfiltered_out_regs); ++ ArgumentShuffle arg_shuffle(in_regs, filtered_out_regs, as_VMStorage(shuffle_reg)); ++ ++#ifndef PRODUCT ++ LogTarget(Trace, foreign, upcall) lt; ++ if (lt.is_enabled()) { ++ ResourceMark rm; ++ LogStream ls(lt); ++ arg_shuffle.print_on(&ls); ++ } ++#endif ++ + int frame_size = frame_bottom_offset; + frame_size = align_up(frame_size, StackAlignmentInBytes); + @@ -68963,29 +69538,28 @@ index 00000000000..ccaa16bb6b1 + + // we have to always spill args since we need to do a call to get the thread + // (and maybe attach it). -+ arg_spilller.generate_spill(_masm, arg_save_area_offset); ++ arg_spiller.generate_spill(_masm, arg_save_area_offset); + preserve_callee_saved_registers(_masm, abi, reg_save_area_offset); + + __ block_comment("{ on_entry"); + __ lea(c_rarg0, Address(SP, frame_data_offset)); ++ __ li(c_rarg1, (intptr_t)receiver); + __ call(CAST_FROM_FN_PTR(address, UpcallLinker::on_entry), relocInfo::runtime_call_type); + __ move(TREG, V0); + __ reinit_heapbase(); + __ block_comment("} on_entry"); + + __ block_comment("{ argument shuffle"); -+ arg_spilller.generate_fill(_masm, arg_save_area_offset); ++ arg_spiller.generate_fill(_masm, arg_save_area_offset); + if (needs_return_buffer) { + assert(ret_buf_offset != -1, "no return buffer allocated"); + __ lea(as_Register(locs.get(StubLocations::RETURN_BUFFER)), Address(SP, ret_buf_offset)); + } -+ arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0, locs); ++ arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0); + __ block_comment("} argument shuffle"); + + __ block_comment("{ receiver "); -+ __ li(shuffle_reg, (intptr_t)receiver); -+ __ resolve_jobject(shuffle_reg, SCR2, SCR1); -+ __ move(j_rarg0, shuffle_reg); ++ __ get_vm_result(j_rarg0, TREG); + __ block_comment("} receiver "); + + __ mov_metadata(Rmethod, entry); @@ -69055,18 +69629,6 @@ index 00000000000..ccaa16bb6b1 + + ////////////////////////////////////////////////////////////////////////////// + -+ __ block_comment("{ exception handler"); -+ -+ intptr_t exception_handler_offset = __ pc() - start; -+ -+ // Native caller has no idea how to handle exceptions, -+ // so we just crash here. Up to callee to catch exceptions. -+ __ verify_oop(V0); -+ __ call(CAST_FROM_FN_PTR(address, UpcallLinker::handle_uncaught_exception), relocInfo::runtime_call_type); -+ __ should_not_reach_here(); -+ -+ __ block_comment("} exception handler"); -+ + _masm->flush(); + +#ifndef PRODUCT @@ -69082,9 +69644,11 @@ index 00000000000..ccaa16bb6b1 + UpcallStub* blob + = UpcallStub::create(name, + &buffer, -+ exception_handler_offset, + receiver, + in_ByteSize(frame_data_offset)); ++ if (blob == nullptr) { ++ return nullptr; ++ } + +#ifndef PRODUCT + if (lt.is_enabled()) { @@ -69165,10 +69729,10 @@ 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..44bca90d2c2 +index 00000000000..c30bf3bf416 --- /dev/null +++ b/src/hotspot/cpu/loongarch/vm_version_loongarch.cpp -@@ -0,0 +1,511 @@ +@@ -0,0 +1,514 @@ +/* + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -69331,8 +69895,6 @@ index 00000000000..44bca90d2c2 + get_cpu_info_stub(&_cpuid_info); + _features |= get_feature_flags_by_cpucfg(); + -+ _supports_cx8 = true; -+ + if (UseG1GC && FLAG_IS_DEFAULT(MaxGCPauseMillis)) { + FLAG_SET_DEFAULT(MaxGCPauseMillis, 150); + } @@ -69582,6 +70144,11 @@ index 00000000000..44bca90d2c2 + UseFPUForSpilling = false; + } + } ++ ++ if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) { ++ FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); ++ } ++ +#endif + + // This machine allows unaligned memory accesses @@ -70574,7 +71141,7 @@ index 00000000000..ab12021832d + return icache_line_size; +} diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp -index a77476e218a..fa8785eb35d 100644 +index 3fc025e5100..3e421c369d7 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -23,6 +23,12 @@ @@ -70590,7 +71157,7 @@ index a77476e218a..fa8785eb35d 100644 // no precompiled headers #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" -@@ -2167,6 +2173,12 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { +@@ -2249,6 +2255,12 @@ bool os::Linux::query_process_memory_info(os::Linux::meminfo_t* info) { return false; } @@ -70603,7 +71170,7 @@ index a77476e218a..fa8785eb35d 100644 #ifdef __GLIBC__ // For Glibc, print a one-liner with the malloc tunables. // Most important and popular is MALLOC_ARENA_MAX, but we are -@@ -2383,7 +2395,7 @@ void os::print_memory_info(outputStream* st) { +@@ -2465,7 +2477,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) { @@ -70612,7 +71179,7 @@ index a77476e218a..fa8785eb35d 100644 // Other platforms have less repetitive cpuinfo files FILE *fp = os::fopen("/proc/cpuinfo", "r"); if (fp) { -@@ -2495,7 +2507,7 @@ void os::jfr_report_memory_info() { +@@ -2577,7 +2589,7 @@ void os::jfr_report_memory_info() { #endif // INCLUDE_JFR @@ -70621,7 +71188,7 @@ index a77476e218a..fa8785eb35d 100644 const char* search_string = "model name"; #elif defined(M68K) const char* search_string = "CPU"; -@@ -4472,6 +4484,44 @@ void os::Linux::numa_init() { +@@ -4401,6 +4413,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; @@ -70667,7 +71234,7 @@ index a77476e218a..fa8785eb35d 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 a7cf69f3164..c6446e02bb8 100644 +index 4b2ccf8e370..5eaa98414ca 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -22,6 +22,12 @@ @@ -70683,7 +71250,7 @@ index a7cf69f3164..c6446e02bb8 100644 #ifndef OS_LINUX_OS_LINUX_HPP #define OS_LINUX_OS_LINUX_HPP -@@ -199,6 +205,8 @@ class os::Linux { +@@ -190,6 +196,8 @@ class os::Linux { // none present @@ -70693,7 +71260,7 @@ index a7cf69f3164..c6446e02bb8 100644 static void numa_init(); diff --git a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp -index 609967128fb..d67deeda164 100644 +index 446449a40e0..0f70070713f 100644 --- a/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp +++ b/src/hotspot/os/linux/systemMemoryBarrier_linux.cpp @@ -22,6 +22,12 @@ @@ -71854,7 +72421,7 @@ 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..79beb476935 +index 00000000000..31bfcba8db6 --- /dev/null +++ b/src/hotspot/os_cpu/linux_loongarch/os_linux_loongarch.cpp @@ -0,0 +1,491 @@ @@ -72331,7 +72898,7 @@ index 00000000000..79beb476935 + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. + address pc = os::fetch_frame_from_context(uc).pc(); -+ print_instructions(st, pc, 4/*native instruction size*/); ++ print_instructions(st, pc); + st->cr(); +} + @@ -72671,7 +73238,7 @@ index 00000000000..3711a7036a1 + HWCAP_LOONGARCH_LBT_MIPS); +} diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp -index be4ee3a3acf..9eb3b3a9dc7 100644 +index 8e2366e5d09..38e5fd7b2c6 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -22,6 +22,12 @@ @@ -72687,7 +73254,7 @@ index be4ee3a3acf..9eb3b3a9dc7 100644 // FORMS.CPP - Definitions for ADL Parser Forms Classes #include "adlc.hpp" -@@ -4144,6 +4150,7 @@ bool MatchRule::is_ideal_membar() const { +@@ -4174,6 +4180,7 @@ bool MatchRule::is_ideal_membar() const { !strcmp(_opType,"MemBarVolatile") || !strcmp(_opType,"MemBarCPUOrder") || !strcmp(_opType,"MemBarStoreStore") || @@ -72696,10 +73263,10 @@ index be4ee3a3acf..9eb3b3a9dc7 100644 } diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp -index 22299b4051b..573ce8ff7b0 100644 +index bdbeb39f89a..c84f830eee7 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp -@@ -43,6 +43,12 @@ +@@ -44,6 +44,12 @@ #include "utilities/bitMap.inline.hpp" #include "utilities/macros.hpp" @@ -72712,7 +73279,7 @@ index 22299b4051b..573ce8ff7b0 100644 Compiler::Compiler() : AbstractCompiler(compiler_c1) { } -@@ -219,7 +225,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { +@@ -222,7 +228,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: @@ -72884,7 +73451,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 a2663adacf0..223837f7ccf 100644 +index 7e46f9d5603..97f98d5a5e0 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -22,6 +22,12 @@ @@ -72913,7 +73480,7 @@ index a2663adacf0..223837f7ccf 100644 #ifndef PRODUCT static LinearScanStatistic _stat_before_alloc; -@@ -3133,9 +3145,6 @@ void LinearScan::do_linear_scan() { +@@ -3135,9 +3147,6 @@ void LinearScan::do_linear_scan() { } } @@ -72923,7 +73490,7 @@ index a2663adacf0..223837f7ccf 100644 { TIME_LINEAR_SCAN(timer_optimize_lir); EdgeMoveOptimizer::optimize(ir()->code()); -@@ -3143,7 +3152,6 @@ void LinearScan::do_linear_scan() { +@@ -3145,7 +3154,6 @@ void LinearScan::do_linear_scan() { // check that cfg is still correct after optimizations ir()->verify(); } @@ -72931,7 +73498,7 @@ index a2663adacf0..223837f7ccf 100644 NOT_PRODUCT(print_lir(1, "Before Code Generation", false)); NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final)); -@@ -5949,9 +5957,13 @@ void EdgeMoveOptimizer::optimize(BlockList* code) { +@@ -5951,9 +5959,13 @@ void EdgeMoveOptimizer::optimize(BlockList* code) { if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) { optimizer.optimize_moves_at_block_end(block); } @@ -72945,7 +73512,7 @@ index a2663adacf0..223837f7ccf 100644 } } -@@ -6368,7 +6380,16 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { +@@ -6370,7 +6382,16 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op; if (prev_branch->stub() == nullptr) { @@ -72962,7 +73529,7 @@ index a2663adacf0..223837f7ccf 100644 LIR_Op2* prev_cmp = nullptr; // There might be a cmove inserted for profiling which depends on the same // compare. If we change the condition of the respective compare, we have -@@ -6408,6 +6429,7 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { +@@ -6410,6 +6431,7 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { prev_cmove->set_in_opr2(t); } } @@ -72971,7 +73538,7 @@ index a2663adacf0..223837f7ccf 100644 } } diff --git a/src/hotspot/share/code/vtableStubs.cpp b/src/hotspot/share/code/vtableStubs.cpp -index 42a8a63a38f..c27a4299e5e 100644 +index eed3dc8e787..c8b58dd459c 100644 --- a/src/hotspot/share/code/vtableStubs.cpp +++ b/src/hotspot/share/code/vtableStubs.cpp @@ -22,6 +22,12 @@ @@ -72987,7 +73554,7 @@ index 42a8a63a38f..c27a4299e5e 100644 #include "precompiled.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" -@@ -102,7 +108,11 @@ int VtableStubs::_itab_stub_size = 0; +@@ -101,7 +107,11 @@ int VtableStubs::_itab_stub_size = 0; #if defined(PRODUCT) // These values are good for the PRODUCT case (no tracing). @@ -73000,7 +73567,7 @@ index 42a8a63a38f..c27a4299e5e 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 28f850938c4..626bfee16a9 100644 +index b8a7c677f7f..e02033a1ff5 100644 --- a/src/hotspot/share/gc/g1/g1Arguments.cpp +++ b/src/hotspot/share/gc/g1/g1Arguments.cpp @@ -23,6 +23,12 @@ @@ -73014,9 +73581,9 @@ index 28f850938c4..626bfee16a9 100644 + */ + #include "precompiled.hpp" + #include "cds/cdsConfig.hpp" #include "gc/g1/g1Arguments.hpp" - #include "gc/g1/g1CardSet.hpp" -@@ -164,6 +170,20 @@ void G1Arguments::initialize_card_set_configuration() { +@@ -168,6 +174,20 @@ void G1Arguments::initialize_card_set_configuration() { void G1Arguments::initialize() { GCArguments::initialize(); assert(UseG1GC, "Error"); @@ -73038,7 +73605,7 @@ index 28f850938c4..626bfee16a9 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 41553e6bf19..d426a240c7e 100644 +index 7f666c0f497..a456386443e 100644 --- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp +++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp @@ -22,6 +22,12 @@ @@ -73095,7 +73662,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 274744d5de2..4f5e6f359dd 100644 +index adf0527681b..a1a76917f39 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -22,6 +22,12 @@ @@ -73121,7 +73688,7 @@ index 274744d5de2..4f5e6f359dd 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 90fae8c3588..752a78db893 100644 +index 41bd15ab000..508e37fa2c4 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -22,6 +22,12 @@ @@ -73137,7 +73704,7 @@ index 90fae8c3588..752a78db893 100644 #include "precompiled.hpp" #include "gc/shared/tlab_globals.hpp" #include "gc/shared/c2/barrierSetC2.hpp" -@@ -263,6 +269,8 @@ public: +@@ -263,6 +269,8 @@ class C2AccessFence: public StackObj { bool is_volatile = (decorators & MO_SEQ_CST) != 0; bool is_acquire = (decorators & MO_ACQUIRE) != 0; @@ -73146,7 +73713,7 @@ index 90fae8c3588..752a78db893 100644 // If reference is volatile, prevent following volatiles ops from // floating up before the volatile access. -@@ -296,6 +304,13 @@ public: +@@ -296,6 +304,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(); @@ -73161,7 +73728,7 @@ index 90fae8c3588..752a78db893 100644 } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp -index 7d31ff02e1a..07dac06aecf 100644 +index d9b28c1bb4d..b6435ac7334 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -22,6 +22,12 @@ @@ -73187,7 +73754,7 @@ index 7d31ff02e1a..07dac06aecf 100644 #endif diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp -index aefec771871..95c0b16d8c6 100644 +index 68e215e9ebc..825650461e8 100644 --- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp @@ -21,6 +21,12 @@ @@ -73203,7 +73770,7 @@ index aefec771871..95c0b16d8c6 100644 #include "precompiled.hpp" #include "c1/c1_FrameMap.hpp" #include "c1/c1_LIR.hpp" -@@ -453,6 +459,10 @@ LIR_Opr ZBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cm +@@ -451,6 +457,10 @@ LIR_Opr ZBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cm #endif access.gen()->lir()->move(cmp_value.result(), cmp_value_opr); @@ -73214,7 +73781,7 @@ index aefec771871..95c0b16d8c6 100644 __ cas_obj(access.resolved_addr()->as_address_ptr()->base(), cmp_value_opr, new_value_zpointer, -@@ -460,12 +470,19 @@ LIR_Opr ZBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cm +@@ -458,12 +468,19 @@ LIR_Opr ZBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cm access.gen()->new_register(T_OBJECT), access.gen()->new_register(T_OBJECT), access.gen()->new_register(T_OBJECT)); @@ -73263,7 +73830,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 ddb6ca32108..0365b9023a0 100644 +index 70439459d35..a9ebc001900 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -22,6 +22,12 @@ @@ -73279,7 +73846,7 @@ index ddb6ca32108..0365b9023a0 100644 #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/symbolTable.hpp" -@@ -1471,7 +1477,7 @@ JRT_ENTRY(void, InterpreterRuntime::prepare_native_call(JavaThread* current, Met +@@ -1461,7 +1467,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 @@ -73289,7 +73856,7 @@ index ddb6ca32108..0365b9023a0 100644 assert(current == JavaThread::current(), "pre-condition"); if (src_address == dest_address) { diff --git a/src/hotspot/share/interpreter/interpreterRuntime.hpp b/src/hotspot/share/interpreter/interpreterRuntime.hpp -index 97cfcb1eae6..622e49f2f77 100644 +index 297585d37e8..c3e9179b02c 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.hpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp @@ -22,6 +22,12 @@ @@ -73343,8 +73910,30 @@ 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 b3a3600deb6..59fd9d3416f 100644 +index 7661b35863c..ad281cad645 100644 --- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp +++ b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -22,6 +22,12 @@ @@ -73360,7 +73949,7 @@ index b3a3600deb6..59fd9d3416f 100644 #ifndef SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP #define SHARE_JFR_UTILITIES_JFRBIGENDIAN_HPP -@@ -103,7 +109,7 @@ inline T JfrBigEndian::read_unaligned(const address location) { +@@ -103,7 +109,7 @@ inline R JfrBigEndian::read_unaligned(const address location) { inline bool JfrBigEndian::platform_supports_unaligned_reads(void) { #if defined(IA32) || defined(AMD64) || defined(PPC) || defined(S390) return true; @@ -73370,7 +73959,7 @@ index b3a3600deb6..59fd9d3416f 100644 #else #warning "Unconfigured platform" diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp -index a4195a04f18..9394ed12b81 100644 +index bac9a786fd9..0bb983e6246 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -22,6 +22,12 @@ @@ -73386,7 +73975,7 @@ index a4195a04f18..9394ed12b81 100644 #include "precompiled.hpp" #include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" -@@ -857,6 +863,17 @@ +@@ -871,6 +877,17 @@ #endif @@ -73404,60 +73993,8 @@ index a4195a04f18..9394ed12b81 100644 #ifdef X86 #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/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp -index b71c213f478..adec80d798a 100644 ---- a/src/hotspot/share/memory/metaspace.cpp -+++ b/src/hotspot/share/memory/metaspace.cpp -@@ -23,6 +23,12 @@ - * - */ - -+/* -+ * This file has been modified by Loongson Technology in 2022. These -+ * modifications are Copyright (c) 2019, 2022, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - #include "precompiled.hpp" - #include "cds/metaspaceShared.hpp" - #include "classfile/classLoaderData.hpp" -@@ -588,12 +594,13 @@ bool Metaspace::class_space_is_initialized() { - // On error, returns an unreserved space. - ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t size) { - --#if defined(AARCH64) || defined(PPC64) -+#if defined(AARCH64) || defined(PPC64) || defined(LOONGARCH64) - const size_t alignment = Metaspace::reserve_alignment(); - - // AArch64: Try to align metaspace class space so that we can decode a - // compressed klass with a single MOVK instruction. We can do this iff the - // compressed class base is a multiple of 4G. -+ - // Additionally, above 32G, ensure the lower LogKlassAlignmentInBytes bits - // of the upper 32-bits of the address are zero so we can handle a shift - // when decoding. -@@ -648,16 +655,16 @@ ReservedSpace Metaspace::reserve_address_space_for_compressed_classes(size_t siz - return rs; - } - } --#endif // defined(AARCH64) || defined(PPC64) -+#endif // defined(AARCH64) || defined(PPC64) || defined(LOONGARCH64) - --#ifdef AARCH64 -+#if defined(AARCH64) || defined(LOONGARCH64) - // Note: on AARCH64, if the code above does not find any good placement, we - // have no recourse. We return an empty space and the VM will exit. - return ReservedSpace(); - #else - // Default implementation: Just reserve anywhere. - return ReservedSpace(size, Metaspace::reserve_alignment(), os::vm_page_size(), (char*)nullptr); --#endif // AARCH64 -+#endif // defined(AARCH64) || defined(LOONGARCH64) - } - - #endif // _LP64 diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp -index 1d5bb7ffa81..37a41655672 100644 +index c7590861032..c192d19e849 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -22,6 +22,12 @@ @@ -73473,7 +74010,7 @@ index 1d5bb7ffa81..37a41655672 100644 #ifndef SHARE_OOPS_STACKCHUNKOOP_INLINE_HPP #define SHARE_OOPS_STACKCHUNKOOP_INLINE_HPP -@@ -335,7 +341,7 @@ inline void stackChunkOopDesc::copy_from_stack_to_chunk(intptr_t* from, intptr_t +@@ -336,7 +342,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"); @@ -73482,7 +74019,7 @@ index 1d5bb7ffa81..37a41655672 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. -@@ -354,7 +360,7 @@ inline void stackChunkOopDesc::copy_from_chunk_to_stack(intptr_t* from, intptr_t +@@ -355,7 +361,7 @@ inline void stackChunkOopDesc::copy_from_chunk_to_stack(intptr_t* from, intptr_t assert(from >= start_address(), ""); assert(from + size <= end_address(), ""); @@ -73492,7 +74029,7 @@ index 1d5bb7ffa81..37a41655672 100644 // 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/classes.hpp b/src/hotspot/share/opto/classes.hpp -index 892ccc6b8ab..6c1b9affcbe 100644 +index 7d1a2cd1db0..f936dd8e748 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -22,6 +22,12 @@ @@ -73517,7 +74054,7 @@ index 892ccc6b8ab..6c1b9affcbe 100644 macro(MinI) macro(MinL) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp -index 47e2ebc5b6d..d25a086de85 100644 +index 8a5e98eda92..a572e02bb9a 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -22,6 +22,12 @@ @@ -73533,7 +74070,7 @@ index 47e2ebc5b6d..d25a086de85 100644 #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" -@@ -3733,6 +3739,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f +@@ -3772,6 +3778,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f n->set_req(MemBarNode::Precedent, top()); } break; @@ -73542,7 +74079,7 @@ index 47e2ebc5b6d..d25a086de85 100644 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/memnode.cpp b/src/hotspot/share/opto/memnode.cpp -index 286f901bd5d..6d9a1641ae2 100644 +index c402a240acb..de8f6835ae6 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -22,6 +22,12 @@ @@ -73558,7 +74095,7 @@ index 286f901bd5d..6d9a1641ae2 100644 #include "precompiled.hpp" #include "classfile/javaClasses.hpp" #include "compiler/compileLog.hpp" -@@ -3276,6 +3282,7 @@ MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { +@@ -3327,6 +3333,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); @@ -73567,7 +74104,7 @@ index 286f901bd5d..6d9a1641ae2 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 e511d64ca6f..23bc631434e 100644 +index 85f4380188d..0ca6096e59f 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -22,6 +22,12 @@ @@ -73583,7 +74120,7 @@ index e511d64ca6f..23bc631434e 100644 #ifndef SHARE_OPTO_MEMNODE_HPP #define SHARE_OPTO_MEMNODE_HPP -@@ -1289,6 +1295,14 @@ public: +@@ -1292,6 +1298,14 @@ class MemBarCPUOrderNode: public MemBarNode { virtual uint ideal_reg() const { return 0; } // not matched in the AD file }; @@ -73599,7 +74136,7 @@ index e511d64ca6f..23bc631434e 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 524e38fcf72..d31bba3b66b 100644 +index 9481b91ce39..e6fe6a706cc 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -22,6 +22,12 @@ @@ -73615,7 +74152,7 @@ index 524e38fcf72..d31bba3b66b 100644 #include "precompiled.hpp" #include "asm/assembler.inline.hpp" #include "asm/macroAssembler.inline.hpp" -@@ -1616,6 +1622,22 @@ void PhaseOutput::fill_buffer(CodeBuffer* cb, uint* blk_starts) { +@@ -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(); @@ -73639,7 +74176,7 @@ index 524e38fcf72..d31bba3b66b 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/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp -index b0bfae08995..fd74e3b3822 100644 +index 250bef15869..1360e72dbbd 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -22,6 +22,12 @@ @@ -73654,25 +74191,24 @@ index b0bfae08995..fd74e3b3822 100644 + #include "precompiled.hpp" #include "cds/cds_globals.hpp" - #include "cds/filemap.hpp" -@@ -1905,7 +1911,7 @@ bool Arguments::check_vm_args_consistency() { + #include "cds/cdsConfig.hpp" +@@ -1844,14 +1850,14 @@ bool Arguments::check_vm_args_consistency() { + } #endif - --#if !defined(X86) && !defined(AARCH64) && !defined(RISCV64) && !defined(ARM) && !defined(PPC64) -+#if !defined(X86) && !defined(AARCH64) && !defined(RISCV64) && !defined(ARM) && !defined(PPC64) && !defined(LOONGARCH64) +-#if !defined(X86) && !defined(AARCH64) && !defined(RISCV64) && !defined(ARM) && !defined(PPC64) && !defined(S390) ++#if !defined(X86) && !defined(AARCH64) && !defined(RISCV64) && !defined(ARM) && !defined(PPC64) && !defined(S390) && !defined(LOONGARCH64) if (LockingMode == LM_LIGHTWEIGHT) { FLAG_SET_CMDLINE(LockingMode, LM_LEGACY); warning("New lightweight locking not supported on this platform"); -@@ -1921,7 +1927,7 @@ bool Arguments::check_vm_args_consistency() { - FLAG_SET_CMDLINE(LockingMode, LM_MONITOR); } + #endif -#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) && !defined(RISCV64) && !defined(S390) +#if !defined(X86) && !defined(AARCH64) && !defined(PPC64) && !defined(RISCV64) && !defined(S390) && !defined(LOONGARCH64) if (LockingMode == LM_MONITOR) { jio_fprintf(defaultStream::error_stream(), - "LockingMode == 0 (LM_MONITOR) is not fully implemented on this architecture"); + "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 --- a/src/hotspot/share/runtime/continuation.cpp @@ -73700,7 +74236,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 36ce7a532eb..51125dd80b1 100644 +index 47906e81f11..3e9ac7a8502 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -22,6 +22,12 @@ @@ -73716,7 +74252,7 @@ index 36ce7a532eb..51125dd80b1 100644 #include "precompiled.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/vmSymbols.hpp" -@@ -774,7 +780,7 @@ frame FreezeBase::freeze_start_frame_yield_stub(frame f) { +@@ -808,7 +814,7 @@ frame FreezeBase::freeze_start_frame_yield_stub(frame f) { } frame FreezeBase::freeze_start_frame_safepoint_stub(frame f) { @@ -73725,7 +74261,7 @@ index 36ce7a532eb..51125dd80b1 100644 f.set_fp(f.real_fp()); // f.set_fp(*Frame::callee_link_address(f)); // ???? #else Unimplemented(); -@@ -832,7 +838,7 @@ inline freeze_result FreezeBase::recurse_freeze_java_frame(const frame& f, frame +@@ -866,7 +872,7 @@ inline freeze_result FreezeBase::recurse_freeze_java_frame(const frame& f, frame _freeze_size += fsize; NOT_PRODUCT(_frames++;) @@ -73734,7 +74270,7 @@ index 36ce7a532eb..51125dd80b1 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 -@@ -1604,7 +1610,7 @@ static freeze_result is_pinned0(JavaThread* thread, oop cont_scope, bool safepoi +@@ -1638,7 +1644,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 @@ -73743,7 +74279,7 @@ index 36ce7a532eb..51125dd80b1 100644 f.set_fp(f.real_fp()); // Instead of this, maybe in ContinuationWrapper::set_last_frame always use the real_fp? #else Unimplemented(); -@@ -2224,8 +2230,8 @@ void ThawBase::recurse_thaw_compiled_frame(const frame& hf, frame& caller, int n +@@ -2279,8 +2285,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) @@ -73789,8 +74325,43 @@ index 7b1ad7e17e1..c7a0246e375 100644 // Use membars when accessing volatile _thread_state. See // 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 +--- a/src/hotspot/share/runtime/objectMonitor.cpp ++++ b/src/hotspot/share/runtime/objectMonitor.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/vmSymbols.hpp" + #include "gc/shared/oopStorage.hpp" +@@ -356,6 +362,9 @@ bool ObjectMonitor::enter(JavaThread* current) { + } + + assert(owner_raw() != current, "invariant"); ++ // Thread _succ != current assertion load reording before Thread if (_succ == current) _succ = nullptr. ++ // But expect order is firstly if (_succ == current) _succ = nullptr then _succ != current assertion. ++ LOONGARCH64_ONLY(DEBUG_ONLY(__asm__ __volatile__ ("dbar 0x700\n");)) + 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) { + } + + // The Spin failed -- Enqueue and park the thread ... ++ LOONGARCH64_ONLY(DEBUG_ONLY(__asm__ __volatile__ ("dbar 0x700\n");)) + assert(_succ != current, "invariant"); + 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 997bf3a968f..7b891a5a6c0 100644 +index 0eb4015a246..9aa9d7ef86f 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -22,6 +22,12 @@ @@ -73804,9 +74375,9 @@ index 997bf3a968f..7b891a5a6c0 100644 + */ + #include "precompiled.hpp" + #include "cds/cdsConfig.hpp" #include "classfile/javaClasses.hpp" - #include "classfile/moduleEntry.hpp" -@@ -1259,7 +1265,8 @@ bool os::is_first_C_frame(frame* fr) { +@@ -1308,7 +1314,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(); @@ -73816,32 +74387,6 @@ index 997bf3a968f..7b891a5a6c0 100644 is_pointer_bad(fr->link_or_null())) return true; // stack grows downwards; if old_fp is below current fp or if the stack -diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp -index fb3f00f38ad..5597181c71f 100644 ---- a/src/hotspot/share/runtime/sharedRuntime.cpp -+++ b/src/hotspot/share/runtime/sharedRuntime.cpp -@@ -22,6 +22,12 @@ - * - */ - -+/* -+ * This file has been modified by Loongson Technology in 2023, These -+ * modifications are Copyright (c) 2018, 2023, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - #include "precompiled.hpp" - #include "classfile/javaClasses.inline.hpp" - #include "classfile/stringTable.hpp" -@@ -3062,7 +3068,7 @@ void AdapterHandlerLibrary::create_native_wrapper(const methodHandle& method) { - struct { double data[20]; } locs_buf; - struct { double data[20]; } stubs_locs_buf; - buffer.insts()->initialize_shared_locs((relocInfo*)&locs_buf, sizeof(locs_buf) / sizeof(relocInfo)); --#if defined(AARCH64) || defined(PPC64) -+#if defined(AARCH64) || defined(PPC64) || defined(LOONGARCH64) - // On AArch64 with ZGC and nmethod entry barriers, we need all oops to be - // in the constant pool to ensure ordering between the barrier and oops - // accesses. For native_wrappers we need a constant. diff --git a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp b/src/hotspot/share/runtime/sharedRuntimeTrig.cpp index fac76262f3c..f41cf843d31 100644 --- a/src/hotspot/share/runtime/sharedRuntimeTrig.cpp @@ -73884,7 +74429,7 @@ index fac76262f3c..f41cf843d31 100644 static double __kernel_sin(double x, double y, int iy) { diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp -index 09ed8d1a7f8..673fce7c88f 100644 +index 34eafb01c6d..c663e01e221 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -22,6 +22,12 @@ @@ -73899,8 +74444,8 @@ index 09ed8d1a7f8..673fce7c88f 100644 + #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" - #include "gc/shared/suspendibleThreadSet.hpp" -@@ -486,7 +492,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread + #include "gc/shared/collectedHeap.hpp" +@@ -493,7 +499,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread } static bool useHeavyMonitors() { @@ -73910,7 +74455,7 @@ index 09ed8d1a7f8..673fce7c88f 100644 #else return false; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp -index 37241534b2b..f7302bea5f7 100644 +index 54d591ff141..425daacb947 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -22,6 +22,12 @@ @@ -73926,7 +74471,7 @@ index 37241534b2b..f7302bea5f7 100644 #include "precompiled.hpp" #include "cds/filemap.hpp" #include "ci/ciField.hpp" -@@ -1567,6 +1573,7 @@ +@@ -1512,6 +1518,7 @@ declare_c2_type(StoreFenceNode, MemBarNode) \ declare_c2_type(MemBarVolatileNode, MemBarNode) \ declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ @@ -73971,7 +74516,7 @@ index bfbaaa58acc..74e56975081 100644 #ifndef PPC #define PPC 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 eee4ae67457..7aaf7f9399c 100644 +index 500e312b2f3..7fe68049d17 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/CABI.java +++ b/src/java.base/share/classes/jdk/internal/foreign/CABI.java @@ -23,6 +23,12 @@ @@ -73987,27 +74532,29 @@ index eee4ae67457..7aaf7f9399c 100644 package jdk.internal.foreign; import jdk.internal.foreign.abi.fallback.FallbackLinker; -@@ -41,6 +47,7 @@ public enum CABI { - WIN_AARCH_64, +@@ -44,6 +50,7 @@ LINUX_PPC_64_LE, LINUX_RISCV_64, + LINUX_S390, + LINUX_LOONGARCH_64, FALLBACK, UNSUPPORTED; -@@ -81,6 +88,10 @@ public enum CABI { +@@ -94,7 +101,11 @@ private static CABI computeCurrent() { if (OperatingSystem.isLinux()) { - return LINUX_RISCV_64; + return LINUX_S390; } +- } + } else if (arch.equals("loongarch64")) { + if (OperatingSystem.isLinux()) { + return LINUX_LOONGARCH_64; + } - } ++ } } else if (FallbackLinker.isSupported()) { 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 b5eb1029ff5..a04d610e59b 100644 +index d90e5acd259..10c77f1de73 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 @@ @@ -74023,26 +74570,24 @@ index b5eb1029ff5..a04d610e59b 100644 package jdk.internal.foreign.abi; import jdk.internal.foreign.SystemLookup; -@@ -32,6 +38,7 @@ import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker; +@@ -30,6 +36,7 @@ + import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; + import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker; import jdk.internal.foreign.abi.fallback.FallbackLinker; - import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker; - import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker; +import jdk.internal.foreign.abi.loongarch64.linux.LinuxLoongArch64Linker; - import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; - import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; - import jdk.internal.foreign.layout.AbstractLayout; -@@ -60,7 +67,8 @@ import java.util.Set; - public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker, - SysVx64Linker, WindowsAArch64Linker, - Windowsx64Linker, LinuxPPC64leLinker, -- LinuxRISCV64Linker, FallbackLinker { -+ LinuxRISCV64Linker, LinuxLoongArch64Linker, -+ FallbackLinker { + import jdk.internal.foreign.abi.ppc64.aix.AixPPC64Linker; + import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64Linker; + import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker; +@@ -66,6 +73,7 @@ + Windowsx64Linker, AixPPC64Linker, + LinuxPPC64Linker, LinuxPPC64leLinker, + LinuxRISCV64Linker, LinuxS390Linker, ++ LinuxLoongArch64Linker, + FallbackLinker { public interface UpcallStubFactory { - MemorySegment makeStub(MethodHandle target, Arena arena); 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 1e417245543..00ee8656fd3 100644 +index 5f625242182..df1b9a65a53 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 @@ @@ -74058,28 +74603,28 @@ index 1e417245543..00ee8656fd3 100644 package jdk.internal.foreign.abi; import jdk.internal.access.JavaLangAccess; -@@ -35,6 +41,7 @@ import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker; +@@ -33,6 +39,7 @@ + import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; + import jdk.internal.foreign.abi.aarch64.windows.WindowsAArch64Linker; import jdk.internal.foreign.abi.fallback.FallbackLinker; - import jdk.internal.foreign.abi.ppc64.linux.LinuxPPC64leLinker; - import jdk.internal.foreign.abi.riscv64.linux.LinuxRISCV64Linker; +import jdk.internal.foreign.abi.loongarch64.linux.LinuxLoongArch64Linker; - import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; - import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; - import jdk.internal.vm.annotation.ForceInline; -@@ -242,6 +249,7 @@ public final class SharedUtils { - case WIN_AARCH_64 -> WindowsAArch64Linker.getInstance(); + 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() { case LINUX_PPC_64_LE -> LinuxPPC64leLinker.getInstance(); case LINUX_RISCV_64 -> LinuxRISCV64Linker.getInstance(); + case LINUX_S390 -> LinuxS390Linker.getInstance(); + case LINUX_LOONGARCH_64 -> LinuxLoongArch64Linker.getInstance(); case FALLBACK -> FallbackLinker.getInstance(); case UNSUPPORTED -> throw new UnsupportedOperationException("Platform does not support native linker"); }; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/LoongArch64Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/LoongArch64Architecture.java new file mode 100644 -index 00000000000..aec9e531708 +index 00000000000..efab2922ddf --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/LoongArch64Architecture.java -@@ -0,0 +1,179 @@ +@@ -0,0 +1,178 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -74112,7 +74657,6 @@ index 00000000000..aec9e531708 +import jdk.internal.foreign.abi.Architecture; +import jdk.internal.foreign.abi.StubLocations; +import jdk.internal.foreign.abi.VMStorage; -+import jdk.internal.foreign.abi.loongarch64.linux.TypeClass; + +public final class LoongArch64Architecture implements Architecture { + public static final Architecture INSTANCE = new LoongArch64Architecture(); @@ -74261,10 +74805,10 @@ index 00000000000..aec9e531708 +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64CallArranger.java new file mode 100644 -index 00000000000..97e84a28b64 +index 00000000000..ab68e36a0c1 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64CallArranger.java -@@ -0,0 +1,472 @@ +@@ -0,0 +1,480 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -74305,12 +74849,10 @@ index 00000000000..97e84a28b64 +import jdk.internal.foreign.abi.CallingSequenceBuilder; +import jdk.internal.foreign.abi.DowncallLinker; +import jdk.internal.foreign.abi.LinkerOptions; -+import jdk.internal.foreign.abi.UpcallLinker; +import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.foreign.abi.VMStorage; +import jdk.internal.foreign.Utils; + -+import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.List; @@ -74353,8 +74895,8 @@ index 00000000000..97e84a28b64 + + public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { + CallingSequenceBuilder csb = new CallingSequenceBuilder(CLinux, forUpcall, options); -+ BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); -+ BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false); ++ BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true, options.allowsHeapAccess()); ++ BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false, false) : new BoxBindingCalculator(false); + + boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout()); + if (returnInMemory) { @@ -74416,7 +74958,7 @@ index 00000000000..97e84a28b64 + this.forArguments = forArguments; + } + -+ // Aggregates or scalars passed on the stack are aligned to the greater of ++ // Aggregates or scalars passed on the stack are aligned to the greatest of + // the type alignment and XLEN bits, but never more than the stack alignment. + void alignStack(long alignment) { + alignment = Utils.alignUp(Math.clamp(alignment, STACK_SLOT_SIZE, 16), STACK_SLOT_SIZE); @@ -74519,12 +75061,14 @@ index 00000000000..97e84a28b64 + Map.entry(STRUCT_REGISTER_XF, STRUCT_REGISTER_X)); + } + -+ static class UnboxBindingCalculator extends BindingCalculator { -+ boolean forArguments; ++ static final class UnboxBindingCalculator extends BindingCalculator { ++ protected final boolean forArguments; ++ private final boolean useAddressPairs; + -+ UnboxBindingCalculator(boolean forArguments) { ++ UnboxBindingCalculator(boolean forArguments, boolean useAddressPairs) { + super(forArguments); + this.forArguments = forArguments; ++ this.useAddressPairs = useAddressPairs; + } + + @Override @@ -74548,9 +75092,17 @@ index 00000000000..97e84a28b64 + bindings.vmStore(storage, carrier); + } + case POINTER -> { -+ bindings.unboxAddress(); + VMStorage storage = storageCalculator.getStorage(StorageType.INTEGER); -+ bindings.vmStore(storage, long.class); ++ if (useAddressPairs) { ++ bindings.dup() ++ .segmentBase() ++ .vmStore(storage, Object.class) ++ .segmentOffsetAllowHeap() ++ .vmStore(null, long.class); ++ } else { ++ bindings.unboxAddress(); ++ bindings.vmStore(storage, long.class); ++ } + } + case STRUCT_REGISTER_X -> { + assert carrier == MemorySegment.class; @@ -74739,10 +75291,10 @@ index 00000000000..97e84a28b64 +} 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..c231a91b1bb +index 00000000000..1669486e747 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/LinuxLoongArch64Linker.java -@@ -0,0 +1,65 @@ +@@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -74773,14 +75325,21 @@ index 00000000000..c231a91b1bb + +import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; ++import jdk.internal.foreign.abi.SharedUtils; + +import java.lang.foreign.FunctionDescriptor; ++import java.lang.foreign.MemoryLayout; ++import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.nio.ByteOrder; ++import java.util.Map; + +public final class LinuxLoongArch64Linker extends AbstractLinker { + ++ static final Map CANONICAL_LAYOUTS = ++ SharedUtils.canonicalLayouts(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT); ++ + public static LinuxLoongArch64Linker getInstance() { + final class Holder { + private static final LinuxLoongArch64Linker INSTANCE = new LinuxLoongArch64Linker(); @@ -74807,13 +75366,18 @@ index 00000000000..c231a91b1bb + protected ByteOrder linkerByteOrder() { + return ByteOrder.LITTLE_ENDIAN; + } ++ ++ @Override ++ public Map canonicalLayouts() { ++ return CANONICAL_LAYOUTS; ++ } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/TypeClass.java new file mode 100644 -index 00000000000..117eb529434 +index 00000000000..c0ea58815d6 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/loongarch64/linux/TypeClass.java -@@ -0,0 +1,217 @@ +@@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Loongson Technology. All rights reserved. @@ -74891,7 +75455,7 @@ index 00000000000..117eb529434 + * Struct will be flattened while classifying. That is, struct{struct{int, double}} will be treated + * same as struct{int, double} and struct{int[2]} will be treated same as struct{int, int}. + * */ -+ private static record FieldCounter(long integerCnt, long floatCnt, long pointerCnt) { ++ private record FieldCounter(long integerCnt, long floatCnt, long pointerCnt) { + static final FieldCounter EMPTY = new FieldCounter(0, 0, 0); + static final FieldCounter SINGLE_INTEGER = new FieldCounter(1, 0, 0); + static final FieldCounter SINGLE_FLOAT = new FieldCounter(0, 1, 0); @@ -74941,39 +75505,40 @@ index 00000000000..117eb529434 + } + } + -+ public static record FlattenedFieldDesc(TypeClass typeClass, long offset, ValueLayout layout) { -+ -+ } ++ public record FlattenedFieldDesc(TypeClass typeClass, long offset, ValueLayout layout) { } + + private static List getFlattenedFieldsInner(long offset, MemoryLayout layout) { -+ if (layout instanceof ValueLayout valueLayout) { -+ TypeClass typeClass = classifyValueType(valueLayout); -+ return List.of(switch (typeClass) { -+ case INTEGER, FLOAT -> new FlattenedFieldDesc(typeClass, offset, valueLayout); -+ default -> throw new IllegalStateException("Should not reach here."); -+ }); -+ } else if (layout instanceof GroupLayout groupLayout) { -+ List fields = new ArrayList<>(); -+ for (MemoryLayout memberLayout : groupLayout.memberLayouts()) { -+ if (memberLayout instanceof PaddingLayout) { ++ return switch (layout) { ++ case ValueLayout valueLayout -> { ++ TypeClass typeClass = classifyValueType(valueLayout); ++ yield List.of(switch (typeClass) { ++ case INTEGER, FLOAT -> new FlattenedFieldDesc(typeClass, offset, valueLayout); ++ default -> throw new IllegalStateException("Should not reach here."); ++ }); ++ } ++ case GroupLayout groupLayout -> { ++ List fields = new ArrayList<>(); ++ for (MemoryLayout memberLayout : groupLayout.memberLayouts()) { ++ if (memberLayout instanceof PaddingLayout) { ++ offset += memberLayout.byteSize(); ++ continue; ++ } ++ fields.addAll(getFlattenedFieldsInner(offset, memberLayout)); + offset += memberLayout.byteSize(); -+ continue; + } -+ fields.addAll(getFlattenedFieldsInner(offset, memberLayout)); -+ offset += memberLayout.byteSize(); ++ yield fields; + } -+ return fields; -+ } else if (layout instanceof SequenceLayout sequenceLayout) { -+ List fields = new ArrayList<>(); -+ MemoryLayout elementLayout = sequenceLayout.elementLayout(); -+ for (long i = 0; i < sequenceLayout.elementCount(); i++) { -+ fields.addAll(getFlattenedFieldsInner(offset, elementLayout)); -+ offset += elementLayout.byteSize(); ++ case SequenceLayout sequenceLayout -> { ++ List fields = new ArrayList<>(); ++ MemoryLayout elementLayout = sequenceLayout.elementLayout(); ++ for (long i = 0; i < sequenceLayout.elementCount(); i++) { ++ fields.addAll(getFlattenedFieldsInner(offset, elementLayout)); ++ offset += elementLayout.byteSize(); ++ } ++ yield fields; + } -+ return fields; -+ } else { -+ throw new IllegalStateException("Cannot get here: " + layout); -+ } ++ case null, default -> throw new IllegalStateException("Cannot get here: " + layout); ++ }; + } + + public static List getFlattenedFields(GroupLayout layout) { @@ -75031,44 +75596,6 @@ index 00000000000..117eb529434 + } + } +} -diff --git a/src/java.base/share/classes/jdk/internal/util/Architecture.java b/src/java.base/share/classes/jdk/internal/util/Architecture.java -index 3d68426ce3d..983c791f07f 100644 ---- a/src/java.base/share/classes/jdk/internal/util/Architecture.java -+++ b/src/java.base/share/classes/jdk/internal/util/Architecture.java -@@ -20,6 +20,14 @@ - * 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. -+ * -+ */ -+ - package jdk.internal.util; - - import jdk.internal.vm.annotation.ForceInline; -diff --git a/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template b/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template -index cd615e600dd..1004e3fe2e4 100644 ---- a/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template -+++ b/src/java.base/share/classes/jdk/internal/util/PlatformProps.java.template -@@ -20,6 +20,14 @@ - * 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. -+ * -+ */ -+ - package jdk.internal.util; - - /** diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp index bebf8d0f05a..44d2a6342a1 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp @@ -75206,7 +75733,7 @@ index 71ed978199c..194088c697a 100644 package sun.jvm.hotspot; import java.rmi.RemoteException; -@@ -38,6 +44,7 @@ import sun.jvm.hotspot.debugger.MachineDescriptionPPC64; +@@ -38,6 +44,7 @@ import sun.jvm.hotspot.debugger.MachineDescriptionAArch64; import sun.jvm.hotspot.debugger.MachineDescriptionRISCV64; import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86; @@ -75214,7 +75741,7 @@ index 71ed978199c..194088c697a 100644 import sun.jvm.hotspot.debugger.NoSuchSymbolException; import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal; import sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal; -@@ -557,6 +564,8 @@ public class HotSpotAgent { +@@ -557,6 +564,8 @@ private void setupDebuggerLinux() { machDesc = new MachineDescriptionAArch64(); } else if (cpu.equals("riscv64")) { machDesc = new MachineDescriptionRISCV64(); @@ -75287,7 +75814,7 @@ index c100c160947..0b87e7922e7 100644 package sun.jvm.hotspot.debugger.linux; import java.io.*; -@@ -33,12 +39,14 @@ import sun.jvm.hotspot.debugger.cdbg.*; +@@ -33,12 +39,14 @@ import sun.jvm.hotspot.debugger.x86.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.debugger.aarch64.*; @@ -75302,7 +75829,7 @@ index c100c160947..0b87e7922e7 100644 import sun.jvm.hotspot.debugger.linux.riscv64.*; import sun.jvm.hotspot.utilities.*; -@@ -93,7 +101,14 @@ class LinuxCDebugger implements CDebugger { +@@ -93,7 +101,14 @@ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); if (pc == null) return null; return LinuxAMD64CFrame.getTopFrame(dbg, pc, context); @@ -75335,7 +75862,7 @@ index 69a34fe2afa..da07fe91258 100644 package sun.jvm.hotspot.debugger.linux; import java.lang.reflect.*; -@@ -29,6 +35,7 @@ import sun.jvm.hotspot.debugger.*; +@@ -29,6 +35,7 @@ import sun.jvm.hotspot.debugger.linux.amd64.*; import sun.jvm.hotspot.debugger.linux.x86.*; import sun.jvm.hotspot.debugger.linux.ppc64.*; @@ -75343,7 +75870,7 @@ index 69a34fe2afa..da07fe91258 100644 class LinuxThreadContextFactory { static ThreadContext createThreadContext(LinuxDebugger dbg) { -@@ -37,7 +44,9 @@ class LinuxThreadContextFactory { +@@ -37,7 +44,9 @@ static ThreadContext createThreadContext(LinuxDebugger dbg) { return new LinuxX86ThreadContext(dbg); } else if (cpu.equals("amd64")) { return new LinuxAMD64ThreadContext(dbg); @@ -75656,7 +76183,7 @@ index 7113a3a497b..de47531db7c 100644 package sun.jvm.hotspot.debugger.posix.elf; import java.io.FileInputStream; -@@ -63,6 +69,8 @@ public interface ELFHeader { +@@ -63,6 +69,8 @@ public static final int ARCH_i860 = 7; /** MIPS architecture type. */ public static final int ARCH_MIPS = 8; @@ -75682,7 +76209,7 @@ index d4a7c17dc85..1b3e5d5e971 100644 package sun.jvm.hotspot.debugger.remote; import java.rmi.*; -@@ -33,6 +39,7 @@ import sun.jvm.hotspot.debugger.cdbg.*; +@@ -33,6 +39,7 @@ import sun.jvm.hotspot.debugger.remote.x86.*; import sun.jvm.hotspot.debugger.remote.amd64.*; import sun.jvm.hotspot.debugger.remote.ppc64.*; @@ -75690,7 +76217,7 @@ index d4a7c17dc85..1b3e5d5e971 100644 /** An implementation of Debugger which wraps a RemoteDebugger, providing remote debugging via RMI. -@@ -61,6 +68,10 @@ public class RemoteDebuggerClient extends DebuggerBase implements JVMDebugger { +@@ -61,6 +68,10 @@ public RemoteDebuggerClient(RemoteDebugger remoteDebugger) throws DebuggerExcept threadFactory = new RemoteAMD64ThreadFactory(this); } else if (cpu.equals("ppc64")) { threadFactory = new RemotePPC64ThreadFactory(this); @@ -75870,7 +76397,7 @@ index 00000000000..4fb9cc7c069 + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java -index d0fa7c8d3f1..81cd749cbb9 100644 +index 4a40525b78a..c5919b7488a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java @@ -22,6 +22,12 @@ @@ -75886,7 +76413,7 @@ index d0fa7c8d3f1..81cd749cbb9 100644 package sun.jvm.hotspot.runtime; import java.util.*; -@@ -36,6 +42,7 @@ import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; +@@ -36,6 +42,7 @@ import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_riscv64.LinuxRISCV64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess; @@ -75894,7 +76421,7 @@ index d0fa7c8d3f1..81cd749cbb9 100644 import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_aarch64.BsdAARCH64JavaThreadPDAccess; -@@ -116,6 +123,8 @@ public class Threads { +@@ -116,6 +123,8 @@ private static synchronized void initialize(TypeDataBase db) { access = new LinuxAARCH64JavaThreadPDAccess(); } else if (cpu.equals("riscv64")) { access = new LinuxRISCV64JavaThreadPDAccess(); @@ -76306,10 +76833,10 @@ index 00000000000..824270e1329 +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java new file mode 100644 -index 00000000000..28027a86a32 +index 00000000000..fd4df59522f --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/loongarch64/LOONGARCH64Frame.java -@@ -0,0 +1,540 @@ +@@ -0,0 +1,541 @@ +/* + * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, Loongson Technology. All rights reserved. @@ -76375,7 +76902,7 @@ index 00000000000..28027a86a32 + private static final int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; + + // Entry frames -+ private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -11; ++ private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -3; + + private static VMReg fp = new VMReg(22 << 1); + @@ -76796,7 +77323,8 @@ index 00000000000..28027a86a32 + } + + public BasicObjectLock interpreterFrameMonitorEnd() { -+ Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0); ++ long n = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getCIntegerAt(0, VM.getVM().getAddressSize(), false); ++ Address result = getFP().addOffsetTo(n * VM.getVM().getAddressSize()); + if (Assert.ASSERTS_ENABLED) { + // make sure the pointer points inside the frame + Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer"); @@ -76991,7 +77519,7 @@ index f4cd4873207..622ddb7349e 100644 package sun.jvm.hotspot.utilities; /** Provides canonicalized OS and CPU information for the rest of the -@@ -50,7 +57,7 @@ public class PlatformInfo { +@@ -50,7 +57,7 @@ public static String getOS() throws UnsupportedPlatformException { public static boolean knownCPU(String cpu) { final String[] KNOWN = @@ -77000,7 +77528,7 @@ index f4cd4873207..622ddb7349e 100644 for(String s : KNOWN) { if(s.equals(cpu)) -@@ -83,6 +90,9 @@ public class PlatformInfo { +@@ -83,6 +90,9 @@ public static String getCPU() throws UnsupportedPlatformException { if (cpu.equals("ppc64le")) return "ppc64"; @@ -78040,8 +78568,34 @@ index 00000000000..6df1b7b3a92 + * The LoongArch64 platform independent portions of the JVMCI API. + */ +package jdk.vm.ci.loongarch64; +diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/services/Services.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/services/Services.java +index d4c657f9cd3..65c372c360a 100644 +--- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/services/Services.java ++++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/services/Services.java +@@ -20,6 +20,13 @@ + * 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. ++ */ ++ + package jdk.vm.ci.services; + + import java.util.ArrayList; +@@ -372,6 +379,7 @@ private static String realArch() { + case ARM: return "arm"; + case S390: return "s390"; + case PPC64: return "ppc64"; ++ case LOONGARCH64: return "loongarch64"; + case OTHER: return "other"; + default: throw new InternalError("missing case for " + arch); + } diff --git a/src/jdk.internal.vm.ci/share/classes/module-info.java b/src/jdk.internal.vm.ci/share/classes/module-info.java -index b4b93f6a747..68fa668e1bc 100644 +index 14f97412b3d..23862a52f22 100644 --- a/src/jdk.internal.vm.ci/share/classes/module-info.java +++ b/src/jdk.internal.vm.ci/share/classes/module-info.java @@ -23,6 +23,12 @@ @@ -78056,8 +78610,8 @@ index b4b93f6a747..68fa668e1bc 100644 + module jdk.internal.vm.ci { exports jdk.vm.ci.services to - jdk.internal.vm.compiler, -@@ -40,5 +46,6 @@ module jdk.internal.vm.ci { + jdk.graal.compiler, +@@ -40,5 +46,6 @@ provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory, jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory, @@ -78065,7 +78619,7 @@ index b4b93f6a747..68fa668e1bc 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 279ed53ba5d..3281346aa23 100644 +index d011dc579b5..7747fc06e05 100644 --- a/src/utils/hsdis/binutils/hsdis-binutils.c +++ b/src/utils/hsdis/binutils/hsdis-binutils.c @@ -44,6 +44,12 @@ @@ -78081,7 +78635,7 @@ index 279ed53ba5d..3281346aa23 100644 /* hsdis.c -- dump a range of addresses as native instructions This implements the plugin protocol required by the HotSpot PrintAssembly option. -@@ -500,6 +506,9 @@ static const char* native_arch_name() { +@@ -502,6 +508,9 @@ static const char* native_arch_name() { #endif #ifdef LIBARCH_riscv64 res = "riscv:rv64"; @@ -78092,7 +78646,7 @@ index 279ed53ba5d..3281346aa23 100644 if (res == NULL) res = "architecture not set in Makefile!"; diff --git a/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java b/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java -index 15a60382245..56caa3fba6e 100644 +index 465999eac7f..ba9629d5e77 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java +++ b/test/hotspot/jtreg/compiler/arguments/TestCodeEntryAlignment.java @@ -22,12 +22,18 @@ @@ -78116,7 +78670,7 @@ index 15a60382245..56caa3fba6e 100644 * @summary Test large CodeEntryAlignments are accepted * @run driver compiler.arguments.TestCodeEntryAlignment diff --git a/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java -index 5153f85c9d7..d758a9b626f 100644 +index 55dfb0460a2..5f36747a394 100644 --- a/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java +++ b/test/hotspot/jtreg/compiler/arraycopy/stress/TestStressArrayCopy.java @@ -21,6 +21,12 @@ @@ -78132,7 +78686,7 @@ index 5153f85c9d7..d758a9b626f 100644 package compiler.arraycopy.stress; import java.util.ArrayList; -@@ -149,6 +155,14 @@ public class TestStressArrayCopy { +@@ -149,6 +155,14 @@ public static void main(String... args) throws Exception { // Alternate configs with other flags configs = alternate(configs, "UseCompressedOops"); configs = alternate(configs, "UseSIMDForMemoryOps"); @@ -78148,7 +78702,7 @@ index 5153f85c9d7..d758a9b626f 100644 // Generic config. configs.add(new ArrayList()); diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java -index 02596b7ee55..fdf206f3434 100644 +index a3c9421a3f9..aa02e31f712 100644 --- a/test/hotspot/jtreg/compiler/c2/TestBit.java +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -21,6 +21,12 @@ @@ -78164,7 +78718,7 @@ index 02596b7ee55..fdf206f3434 100644 package compiler.c2; import jdk.test.lib.process.OutputAnalyzer; -@@ -33,7 +39,7 @@ import jdk.test.lib.process.ProcessTools; +@@ -33,7 +39,7 @@ * @library /test/lib / * * @requires vm.flagless @@ -78174,7 +78728,7 @@ index 02596b7ee55..fdf206f3434 100644 * * @run driver compiler.c2.TestBit diff --git a/test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java b/test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java -index f5b37f229d0..a0eddb2ef1f 100644 +index 2e8fdd1aea4..f6854d59044 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/CmpUWithZero.java @@ -21,6 +21,12 @@ @@ -78190,17 +78744,17 @@ index f5b37f229d0..a0eddb2ef1f 100644 package compiler.c2.irTests; import compiler.lib.ir_framework.*; -@@ -29,7 +35,7 @@ import compiler.lib.ir_framework.*; +@@ -29,7 +35,7 @@ * @test * bug 8290529 * @summary verify that x 1) & -- * os.arch=="aarch64" & vm.cpu.features ~= ".*svebitperm.*")) -+ * os.arch=="aarch64" & vm.cpu.features ~= ".*svebitperm.*") | -+ * os.arch=="loongarch64") + * (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 6d1943ca145..1d80230aa42 100644 +index 99a594ade69..61fa03381c5 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestCompareUnsigned.java @@ -20,6 +20,13 @@ @@ -78424,12 +78978,12 @@ index 6d1943ca145..1d80230aa42 100644 package compiler.intrinsics; import compiler.lib.ir_framework.*; -@@ -30,7 +37,7 @@ import jdk.test.lib.Utils; +@@ -30,7 +37,7 @@ * @test * @key randomness * @bug 8283726 8287925 -- * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" -+ * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="loongarch64" +- * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" ++ * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" | os.arch=="loongarch64" * @summary Test the intrinsics implementation of Integer/Long::compareUnsigned * @library /test/lib / * @run driver compiler.intrinsics.TestCompareUnsigned @@ -78522,7 +79076,7 @@ index 54fa7657851..ec35129aae8 100644 * @run driver compiler.intrinsics.TestFloatIsInfinite */ diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestIntegerUnsignedDivMod.java b/test/hotspot/jtreg/compiler/intrinsics/TestIntegerUnsignedDivMod.java -index 1b214c32391..5f997a72c4a 100644 +index 05832452bca..a9e4f8fb38d 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestIntegerUnsignedDivMod.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestIntegerUnsignedDivMod.java @@ -21,10 +21,16 @@ @@ -78537,14 +79091,14 @@ index 1b214c32391..5f997a72c4a 100644 + /** * @test - * @summary Test x86_64 intrinsic for divideUnsigned() and remainderUnsigned() methods for Integer --* @requires os.arch=="amd64" | os.arch=="x86_64" -+* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="loongarch64" + * @summary Test intrinsic for divideUnsigned() and remainderUnsigned() methods for Integer +-* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" ++* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" | os.arch=="loongarch64" * @library /test/lib / * @run driver compiler.intrinsics.TestIntegerUnsignedDivMod */ diff --git a/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java b/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java -index ee9c6499902..32b1d54a3e3 100644 +index 88fd46c4325..322414d04c3 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java +++ b/test/hotspot/jtreg/compiler/intrinsics/TestLongUnsignedDivMod.java @@ -21,10 +21,16 @@ @@ -78559,14 +79113,14 @@ index ee9c6499902..32b1d54a3e3 100644 + /** * @test - * @summary Test x86_64 intrinsic for divideUnsigned() and remainderUnsigned() methods for Long --* @requires os.arch=="amd64" | os.arch=="x86_64" -+* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="loongarch64" + * @summary Test intrinsic for divideUnsigned() and remainderUnsigned() methods for Long +-* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" ++* @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" | os.arch=="loongarch64" * @library /test/lib / * @run driver compiler.intrinsics.TestLongUnsignedDivMod */ diff --git a/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java b/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java -index a3b708fab81..b404447695f 100644 +index 55f8375332d..ff5d931ec51 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java +++ b/test/hotspot/jtreg/compiler/intrinsics/chacha/TestChaCha20.java @@ -22,6 +22,12 @@ @@ -78582,21 +79136,34 @@ index a3b708fab81..b404447695f 100644 package compiler.intrinsics.chacha; import java.util.ArrayList; -@@ -97,6 +103,12 @@ public class TestChaCha20 { - System.out.println("Setting up ASIMD worker"); - configs.add(new ArrayList()); +@@ -38,7 +44,8 @@ + * @library /test/lib + * @requires (vm.cpu.features ~= ".*avx512.*" | vm.cpu.features ~= ".*avx2.*" | vm.cpu.features ~= ".*avx.*") | + * (os.arch=="aarch64" & vm.cpu.features ~= ".*simd.*") | +- * (os.arch == "riscv64" & vm.cpu.features ~= ".*v,.*") ++ * (os.arch == "riscv64" & vm.cpu.features ~= ".*v,.*") | ++ * (os.arch == "loongarch64" & vm.cpu.features ~= ".*lsx.*") + * @build compiler.intrinsics.chacha.ExerciseChaCha20 + * jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox +@@ -110,8 +117,14 @@ public static void main(String... args) throws Exception { + System.out.println("Setting up vector worker"); + configs.add(List.of("-XX:+UseRVV")); } + } else if (Platform.isLoongArch64()) { + // LoongArch64 intrinsics require the lsx instructions -+ if (containsFuzzy(cpuFeatures, "lsx")) { ++ if (containsFuzzy(cpuFeatures, "lsx", false)) { + System.out.println("Setting up LSX worker"); + configs.add(new ArrayList()); + } } else { - // We only have ChaCha20 intrinsics on x64 and aarch64 +- // We only have ChaCha20 intrinsics on x64, aarch64 and riscv64 ++ // We only have ChaCha20 intrinsics on x64, aarch64, riscv64 and loongarch64 // currently. If the platform is neither of these then + // 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 eeba614de4f..5a2f293e259 100644 +index 0541121c127..d9fe8c91dc4 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/Binary16Conversion.java @@ -21,11 +21,17 @@ @@ -78642,7 +79209,7 @@ index 38060dfb504..151caa94346 100644 * @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 4afda120709..230aef2fb58 100644 +index 492901f0046..e95554fa944 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/TestAllFloat16ToFloat.java @@ -21,11 +21,17 @@ @@ -78665,7 +79232,7 @@ index 4afda120709..230aef2fb58 100644 * @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 062e6804897..42a9d239e06 100644 +index b4ba578c9f2..27e6b86abe2 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/TestConstFloat16ToFloat.java @@ -21,11 +21,17 @@ @@ -78704,7 +79271,7 @@ index 468cd83d7a2..40d2b03e301 100644 package compiler.intrinsics.sha.cli.testcases; import compiler.intrinsics.sha.cli.DigestOptionsBase; -@@ -32,7 +38,7 @@ import jdk.test.lib.cli.predicate.OrPredicate; +@@ -32,7 +38,7 @@ /** * Generic test case for SHA-related options targeted to any CPU except @@ -78713,7 +79280,7 @@ index 468cd83d7a2..40d2b03e301 100644 */ public class GenericTestCaseForOtherCPU extends DigestOptionsBase.TestCase { -@@ -44,14 +50,15 @@ public class GenericTestCaseForOtherCPU extends +@@ -44,14 +50,15 @@ public GenericTestCaseForOtherCPU(String optionName) { } public GenericTestCaseForOtherCPU(String optionName, boolean checkUseSHA) { @@ -78732,10 +79299,10 @@ index 468cd83d7a2..40d2b03e301 100644 this.checkUseSHA = checkUseSHA; } diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java -index afc308c37dd..5b949dfa19a 100644 +index 76ef4766159..859abf2aa2e 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java +++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestCountPositives.java -@@ -21,13 +21,21 @@ +@@ -21,6 +21,12 @@ * questions. */ @@ -78745,28 +79312,47 @@ index afc308c37dd..5b949dfa19a 100644 + * available on the same license terms set forth above. + */ + - package compiler.intrinsics.string; + /* + * @test + * @bug 8281146 +@@ -55,6 +61,7 @@ + import java.util.Random; + import java.util.stream.IntStream; +import jdk.test.lib.Platform; + import jdk.test.lib.Utils; + + public class TestCountPositives { +@@ -127,7 +134,7 @@ private static void test_countPositives(int off, int len, int ng, int ngOffset) + int calculated = Helper.StringCodingCountPositives(bytes, off, len); + int expected = countPositives(bytes, off, len); + if (calculated != expected) { +- if (expected != len && ng >= 0 && calculated >= 0 && calculated < expected) { ++ if (!Platform.isLoongArch64() && expected != len && calculated >= 0 && calculated < expected) { + // allow intrinsics to return early with a lower value, + // but only if we're not expecting the full length (no + // negative bytes) +diff --git a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringCompareToDifferentLength.java b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringCompareToDifferentLength.java +index 26bc03c271b..606f0d4f17d 100644 +--- a/test/hotspot/jtreg/compiler/intrinsics/string/TestStringCompareToDifferentLength.java ++++ b/test/hotspot/jtreg/compiler/intrinsics/string/TestStringCompareToDifferentLength.java +@@ -22,9 +22,15 @@ + * 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 8999999 - * @summary Validates StringCoding.countPositives intrinsic with a small range of tests. -- * @library /compiler/patches -+ * @library /compiler/patches /test/lib - * - * @build java.base/java.lang.Helper - * @run main compiler.intrinsics.string.TestCountPositives -@@ -91,7 +99,7 @@ public class TestCountPositives { - int calculated = Helper.StringCodingCountPositives(tBa, off, len); - int expected = countPositives(tBa, off, len); - if (calculated != expected) { -- if (expected != len && calculated >= 0 && calculated < expected) { -+ if (!Platform.isLoongArch64() && expected != len && calculated >= 0 && calculated < expected) { - // allow intrinsics to return early with a lower value, - // but only if we're not expecting the full length (no - // negative bytes) +- * @requires os.arch=="aarch64" | os.arch=="riscv64" ++ * @requires os.arch=="aarch64" | os.arch=="riscv64" | os.arch=="loongarch64" + * @summary String::compareTo implementation uses different algorithms for + * 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 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInstallationTest.java @@ -78790,7 +79376,7 @@ index 7483c45a654..68c280f1f39 100644 import jdk.vm.ci.riscv64.RISCV64; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.CodeCacheProvider; -@@ -31,6 +39,7 @@ import jdk.vm.ci.code.InstalledCode; +@@ -31,6 +39,7 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.code.test.aarch64.AArch64TestAssembler; import jdk.vm.ci.code.test.amd64.AMD64TestAssembler; @@ -78798,7 +79384,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 @@ public class CodeInstallationTest { +@@ -80,6 +89,8 @@ private TestAssembler createAssembler() { return new AArch64TestAssembler(codeCache, config); } else if (arch instanceof RISCV64) { return new RISCV64TestAssembler(codeCache, config); @@ -79620,7 +80206,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 955ecd5b475..56c4531b8b0 100644 +index 9e91268edff..2b25abb24c5 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 @@ @@ -79636,19 +80222,19 @@ index 955ecd5b475..56c4531b8b0 100644 package compiler.lib.ir_framework; import compiler.lib.ir_framework.driver.irmatching.mapping.*; -@@ -277,13 +283,13 @@ public class IRNode { +@@ -375,13 +381,13 @@ public static final String CHECKCAST_ARRAY = PREFIX + "CHECKCAST_ARRAY" + POSTFIX; static { -- String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|or).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END; -+ String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|or|li).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END; +- String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|mv|or).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END; ++ String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*:|.*(?i:mov|mv|or|li).*precise \\[.*:.*\\R.*(cmp|CMP|CLR))" + END; optoOnly(CHECKCAST_ARRAY, regex); } public static final String CHECKCAST_ARRAY_OF = COMPOSITE_PREFIX + "CHECKCAST_ARRAY_OF" + POSTFIX; static { -- String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*" + IS_REPLACED + ":|.*(?i:mov|or).*precise \\[.*" + IS_REPLACED + ":.*\\R.*(cmp|CMP|CLR))" + END; -+ String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*" + IS_REPLACED + ":|.*(?i:mov|or|li).*precise \\[.*" + IS_REPLACED + ":.*\\R.*(cmp|CMP|CLR))" + END; +- String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*" + IS_REPLACED + ":|.*(?i:mov|mv|or).*precise \\[.*" + IS_REPLACED + ":.*\\R.*(cmp|CMP|CLR))" + END; ++ String regex = "(((?i:cmp|CLFI|CLR).*precise \\[.*" + IS_REPLACED + ":|.*(?i:mov|mv|or|li).*precise \\[.*" + IS_REPLACED + ":.*\\R.*(cmp|CMP|CLR))" + END; optoOnly(CHECKCAST_ARRAY_OF, regex); } @@ -79677,10 +80263,10 @@ index b1495d00548..61a9eacdf48 100644 * @run main/othervm -Xbatch -XX:LoopUnrollLimit=250 * -XX:CompileCommand=exclude,compiler.loopopts.superword.ReductionPerf::main diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java -index afe36ee89ef..f1b1ff5f4fc 100644 +index b9a3028978f..36efb0b63ba 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestRangeCheckHoistingScaledIV.java -@@ -21,12 +21,18 @@ +@@ -21,13 +21,19 @@ * questions. */ @@ -79695,11 +80281,12 @@ index afe36ee89ef..f1b1ff5f4fc 100644 * @bug 8289996 * @summary Test range check hoisting for some scaled iv at array index * @library /test/lib / + * @requires vm.flagless - * @requires vm.debug & vm.compiler2.enabled & (os.simpleArch == "x64" | os.arch == "aarch64") + * @requires vm.debug & vm.compiler2.enabled & (os.simpleArch == "x64" | os.arch == "aarch64" | os.arch == "loongarch64") * @modules jdk.incubator.vector - * @compile --enable-preview -source ${jdk.version} TestRangeCheckHoistingScaledIV.java - * @run main/othervm --enable-preview compiler.rangechecks.TestRangeCheckHoistingScaledIV + * @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 --- a/test/hotspot/jtreg/compiler/runtime/TestConstantsInError.java @@ -79717,7 +80304,7 @@ index df221959bb5..a15ac48e3fa 100644 /* * @test * @bug 8279822 -@@ -130,7 +136,7 @@ public abstract class TestConstantsInError implements OutputProcessor { +@@ -130,7 +136,7 @@ public void process(OutputAnalyzer results, boolean isC1) { results.shouldMatch("Test_C1/.*::test \\(3 bytes\\)$") .shouldMatch("Test_C2/.*::test \\(3 bytes\\)$"); @@ -79726,7 +80313,7 @@ index df221959bb5..a15ac48e3fa 100644 results.shouldMatch("Test_C1/.*::test \\(3 bytes\\) made not entrant") .shouldMatch("Test_C2/.*::test \\(3 bytes\\) made not entrant"); } else { -@@ -168,7 +174,7 @@ public abstract class TestConstantsInError implements OutputProcessor { +@@ -168,7 +174,7 @@ public void process(OutputAnalyzer results, boolean isC1) { .shouldMatch("Test_MH3/.*::test \\(3 bytes\\)$") .shouldMatch("Test_MH4/.*::test \\(3 bytes\\)$"); @@ -79735,7 +80322,7 @@ index df221959bb5..a15ac48e3fa 100644 results.shouldMatch("Test_MH1/.*::test \\(3 bytes\\) made not entrant") .shouldMatch("Test_MH2/.*::test \\(3 bytes\\) made not entrant") .shouldMatch("Test_MH3/.*::test \\(3 bytes\\) made not entrant") -@@ -191,7 +197,7 @@ public abstract class TestConstantsInError implements OutputProcessor { +@@ -191,7 +197,7 @@ public void process(OutputAnalyzer results, boolean isC1) { results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\)$") .shouldMatch("Test_MT2/.*::test \\(3 bytes\\)$"); @@ -79744,7 +80331,7 @@ index df221959bb5..a15ac48e3fa 100644 results.shouldMatch("Test_MT1/.*::test \\(3 bytes\\) made not entrant") .shouldMatch("Test_MT2/.*::test \\(3 bytes\\) made not entrant"); } else { -@@ -235,7 +241,7 @@ public abstract class TestConstantsInError implements OutputProcessor { +@@ -235,7 +241,7 @@ public void process(OutputAnalyzer results, boolean isC1) { .shouldMatch("Test_CD3.*::test \\(3 bytes\\)$") .shouldMatch("Test_CD4.*::test \\(3 bytes\\)$"); @@ -79754,10 +80341,10 @@ index df221959bb5..a15ac48e3fa 100644 .shouldMatch("Test_CD2.*::test \\(3 bytes\\) made not entrant") .shouldMatch("Test_CD3.*::test \\(3 bytes\\) made not entrant") diff --git a/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java b/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java -index 7ae227e783e..479f8196195 100644 +index 5dd938442cc..2ec4cab8f62 100644 --- a/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java +++ b/test/hotspot/jtreg/compiler/sharedstubs/SharedStubToInterpTest.java -@@ -22,13 +22,19 @@ +@@ -22,6 +22,12 @@ * */ @@ -79768,16 +80355,17 @@ index 7ae227e783e..479f8196195 100644 + */ + /** - * @test SharedStubToInterpTest - * @summary Checks that stubs to the interpreter can be shared for static or final method. + * @test id=C1 * @bug 8280481 - * @library /test/lib +@@ -34,7 +40,7 @@ * -- * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="i386" | os.arch=="x86" | os.arch=="aarch64" | os.arch=="riscv64" -+ * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="i386" | os.arch=="x86" | os.arch=="aarch64" | os.arch=="riscv64" | os.arch=="loongarch64" + * @test id=C2 + * @requires vm.opt.TieredStopAtLevel == null & vm.opt.TieredCompilation == null +- * @requires vm.simpleArch == "x86" | vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" ++ * @requires vm.simpleArch == "x86" | vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" | vm.simpleArch == "loongarch64" * @requires vm.debug + * @run driver compiler.sharedstubs.SharedStubToInterpTest -XX:-TieredCompilation * - * @run driver compiler.sharedstubs.SharedStubToInterpTest 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 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -79795,7 +80383,7 @@ index 689c7c8cc2f..f734c1baa3f 100644 package compiler.testlibrary.sha.predicate; import jdk.test.lib.Platform; -@@ -61,19 +67,22 @@ public class IntrinsicPredicates { +@@ -61,19 +67,22 @@ public static final BooleanSupplier MD5_INSTRUCTION_AVAILABLE = new OrPredicate(new CPUSpecificPredicate("aarch64.*", null, null), @@ -79820,7 +80408,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 @@ public class IntrinsicPredicates { +@@ -81,12 +90,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), @@ -79854,7 +80442,7 @@ index 35f357c22f2..e0643272e83 100644 package compiler.vectorapi; import compiler.lib.ir_framework.*; -@@ -34,7 +41,7 @@ import jdk.incubator.vector.VectorMask; +@@ -34,7 +41,7 @@ * @modules jdk.incubator.vector * @library /test/lib / * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*sse4.*" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) @@ -79864,7 +80452,7 @@ index 35f357c22f2..e0643272e83 100644 */ public class TestVectorTest { diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java -index 86dccb66e9b..d40d580a07e 100644 +index 426dec67019..ea25a81a354 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java @@ -22,6 +22,12 @@ @@ -79880,7 +80468,7 @@ index 86dccb66e9b..d40d580a07e 100644 package compiler.vectorapi; import compiler.lib.ir_framework.*; -@@ -45,7 +51,7 @@ import jdk.test.lib.Utils; +@@ -45,7 +51,7 @@ * @key randomness * @library /test/lib / * @summary Add identity transformations for vector logic operations @@ -79890,7 +80478,7 @@ index 86dccb66e9b..d40d580a07e 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 7205c262280..66baaa34d94 100644 +index 154567922bd..d81a90f2fcb 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorReverseBytesTest.java @@ -21,6 +21,12 @@ @@ -79906,7 +80494,7 @@ index 7205c262280..66baaa34d94 100644 package compiler.vectorapi; import compiler.lib.ir_framework.*; -@@ -42,7 +48,7 @@ import jdk.test.lib.Utils; +@@ -42,7 +48,7 @@ * @library /test/lib / * @summary [vectorapi] REVERSE_BYTES for byte type should not emit any instructions * @requires vm.compiler2.enabled @@ -79915,8 +80503,145 @@ index 7205c262280..66baaa34d94 100644 * @modules jdk.incubator.vector * * @run driver compiler.vectorapi.VectorReverseBytesTest +diff --git a/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastLASX.java b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastLASX.java +new file mode 100644 +index 00000000000..3298628333e +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/TestVectorCastLASX.java +@@ -0,0 +1,51 @@ ++/* ++ * Copyright (c) 2023, 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. ++ */ ++ ++package compiler.vectorapi.reshape; ++ ++import compiler.vectorapi.reshape.tests.TestVectorCast; ++import compiler.vectorapi.reshape.utils.TestCastMethods; ++import compiler.vectorapi.reshape.utils.VectorReshapeHelper; ++ ++/* ++ * @test ++ * @enablePreview ++ * @key randomness ++ * @modules jdk.incubator.vector ++ * @modules java.base/jdk.internal.misc ++ * @summary Test that vector cast intrinsics work as intended on lasx. ++ * @requires vm.cpu.features ~= ".*lasx.*" ++ * @library /test/lib / ++ * @run main compiler.vectorapi.reshape.TestVectorCastLASX ++ */ ++public class TestVectorCastLASX { ++ public static void main(String[] args) { ++ VectorReshapeHelper.runMainHelper( ++ TestVectorCast.class, ++ TestCastMethods.LASX_CAST_TESTS.stream(), ++ "-XX:+UseLASX"); ++ } ++} ++ ++ +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 +--- a/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.java ++++ b/test/hotspot/jtreg/compiler/vectorapi/reshape/utils/TestCastMethods.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. ++ */ ++ + package compiler.vectorapi.reshape.utils; + + import java.util.List; +@@ -336,4 +342,62 @@ + makePair(SSPEC128, ISPEC128, true), + makePair(ISPEC64, LSPEC128, true) + ); ++ ++ public static final List LASX_CAST_TESTS = List.of( ++ makePair(BSPEC64, SSPEC128), ++ makePair(BSPEC128, SSPEC256), ++ makePair(BSPEC64, ISPEC256), ++ makePair(BSPEC64, FSPEC256), ++ makePair(SSPEC128, BSPEC64), ++ makePair(SSPEC256, BSPEC128), ++ makePair(SSPEC64, ISPEC128), ++ makePair(SSPEC128, ISPEC256), ++ makePair(SSPEC64, LSPEC256), ++ makePair(SSPEC64, FSPEC128), ++ makePair(SSPEC128, FSPEC256), ++ makePair(SSPEC64, DSPEC256), ++ makePair(ISPEC256, BSPEC64), ++ makePair(ISPEC128, SSPEC64), ++ makePair(ISPEC256, SSPEC128), ++ makePair(ISPEC64, LSPEC128), ++ makePair(ISPEC128, LSPEC256), ++ makePair(ISPEC64, FSPEC64), ++ makePair(ISPEC128, FSPEC128), ++ makePair(ISPEC256, FSPEC256), ++ makePair(ISPEC64, DSPEC128), ++ makePair(ISPEC128, DSPEC256), ++ makePair(LSPEC256, SSPEC64), ++ makePair(LSPEC128, ISPEC64), ++ makePair(LSPEC256, ISPEC128), ++ makePair(LSPEC128, FSPEC64), ++ makePair(LSPEC256, FSPEC128), ++ makePair(LSPEC128, DSPEC128), ++ makePair(LSPEC256, DSPEC256), ++ makePair(FSPEC256, BSPEC64), ++ makePair(FSPEC128, SSPEC64), ++ makePair(FSPEC256, SSPEC128), ++ makePair(FSPEC64, ISPEC64), ++ makePair(FSPEC128, ISPEC128), ++ makePair(FSPEC256, ISPEC256), ++ makePair(FSPEC64, LSPEC128), ++ makePair(FSPEC128, LSPEC256), ++ makePair(FSPEC64, DSPEC128), ++ makePair(FSPEC128, DSPEC256), ++ makePair(DSPEC256, SSPEC64), ++ makePair(DSPEC128, ISPEC64), ++ makePair(DSPEC256, ISPEC128), ++ makePair(DSPEC128, LSPEC128), ++ makePair(DSPEC256, LSPEC256), ++ makePair(DSPEC128, FSPEC64), ++ makePair(DSPEC256, FSPEC128), ++ makePair(BSPEC64, SSPEC128, true), ++ makePair(BSPEC128, SSPEC256, true), ++ makePair(BSPEC64, ISPEC256, true), ++ makePair(SSPEC64, ISPEC128, true), ++ makePair(SSPEC128, ISPEC256, true), ++ makePair(SSPEC64, LSPEC256, true), ++ makePair(ISPEC64, LSPEC128, true), ++ makePair(ISPEC128, LSPEC256, true) ++ ); ++ + } diff --git a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java -index e15a4c834cd..ccd8cab78e0 100644 +index e3baed37804..18b9333b1d1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java @@ -21,6 +21,12 @@ @@ -79932,7 +80657,7 @@ index e15a4c834cd..ccd8cab78e0 100644 package compiler.c2.irTests; import compiler.lib.ir_framework.*; -@@ -34,7 +40,7 @@ import jdk.test.lib.Utils; +@@ -34,7 +40,7 @@ * @library /test/lib / * @requires vm.compiler2.enabled * @requires (os.simpleArch == "x64" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) @@ -79942,7 +80667,7 @@ index e15a4c834cd..ccd8cab78e0 100644 */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java -index bb2bb994bc9..324e80e2794 100644 +index 889cc68f876..a9e769ef99c 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestBufferVectorization.java @@ -21,6 +21,12 @@ @@ -79968,7 +80693,7 @@ index bb2bb994bc9..324e80e2794 100644 * @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 531d82abcc2..f4d9d6b604d 100644 +index 49035332fa4..8a1f3aa6882 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java @@ -21,12 +21,18 @@ @@ -79992,7 +80717,7 @@ index 531d82abcc2..f4d9d6b604d 100644 * @run driver compiler.vectorization.TestFloatConversionsVector */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java -index c64b851096d..8dcfbad3994 100644 +index abbabca0f2a..b7bde7068b5 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java @@ -21,13 +21,20 @@ @@ -80011,14 +80736,14 @@ index c64b851096d..8dcfbad3994 100644 * @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.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) -+* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) | +-* (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 6a709849b9c..0a209d2519a 100644 +index e23accd27b0..e5b7682a7d1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopulateIndex.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopulateIndex.java @@ -21,13 +21,20 @@ @@ -80037,14 +80762,14 @@ index 6a709849b9c..0a209d2519a 100644 * @summary Test vectorization of loop induction variable usage in the loop * @requires vm.compiler2.enabled * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | --* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) -+* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) | +-* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") ++* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*") | +* (os.simpleArch == "loongarch64") * @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 a30015d73f8..03cd80994be 100644 +index 1144186d8e5..f36bb209a6b 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBitsVector.java @@ -20,12 +20,19 @@ @@ -80069,7 +80794,7 @@ index a30015d73f8..03cd80994be 100644 * @run driver compiler.vectorization.TestReverseBitsVector */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java -index 2d399fbd274..e9b9f6e2415 100644 +index 47813e2790e..d30f2d3d177 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java @@ -20,12 +20,19 @@ @@ -80094,10 +80819,10 @@ index 2d399fbd274..e9b9f6e2415 100644 * @run driver compiler.vectorization.TestReverseBytes */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSignumVector.java b/test/hotspot/jtreg/compiler/vectorization/TestSignumVector.java -index bf6a10b855f..b97c0461eaa 100644 +index 66943d68a67..aee6ecfa703 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestSignumVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestSignumVector.java -@@ -21,12 +21,18 @@ +@@ -21,6 +21,12 @@ * questions. */ @@ -80110,15 +80835,17 @@ index bf6a10b855f..b97c0461eaa 100644 /** * @test * @bug 8282711 8290249 - * @summary Accelerate Math.signum function for AVX, AVX512 and aarch64 (Neon and SVE) +@@ -28,7 +34,7 @@ + * and riscv64 (vector) * @requires vm.compiler2.enabled -- * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx.*") | os.arch == "aarch64" -+ * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx.*") | os.arch == "aarch64" | os.arch == "loongarch64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx.*") | 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.vectorization.TestSignumVector */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java -index f9916fd63ec..2ec7b2b816a 100644 +index a4eca0fe8dd..de44f60520a 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayIndexFillTest.java @@ -21,6 +21,12 @@ @@ -80140,11 +80867,11 @@ index f9916fd63ec..2ec7b2b816a 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java -index e4e68cc3fd7..a1324e094c2 100644 +index 2e7302bba05..964c03955d1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayInvariantFillTest.java @@ -21,6 +21,12 @@ @@ -80160,17 +80887,17 @@ index e4e68cc3fd7..a1324e094c2 100644 /* * @test * @summary Vectorization test on array invariant fill -@@ -36,7 +42,7 @@ - * -XX:-OptimizeFill +@@ -41,7 +47,7 @@ + * -XX:+OptimizeFill * compiler.vectorization.runner.ArrayInvariantFillTest * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java -index 1d73221a549..f8222d37d4b 100644 +index 74262142247..920f0418e10 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayShiftOpTest.java @@ -21,6 +21,12 @@ @@ -80192,14 +80919,14 @@ index 1d73221a549..f8222d37d4b 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @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 9bb0c670c55..2d8097f4e62 100644 +index a3fcdbaa9b0..3edbd0dd0ec 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicDoubleOpTest.java -@@ -21,6 +21,12 @@ +@@ -22,6 +22,12 @@ * questions. */ @@ -80212,17 +80939,17 @@ index 9bb0c670c55..2d8097f4e62 100644 /* * @test * @summary Vectorization test on basic double operations -@@ -35,7 +41,7 @@ +@@ -36,7 +42,7 @@ * -XX:+WhiteBoxAPI * compiler.vectorization.runner.BasicDoubleOpTest * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java -index a07fcfa9ca2..50e6580f6d3 100644 +index e2bf0492d2a..47a7a2b4e13 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicFloatOpTest.java @@ -21,6 +21,12 @@ @@ -80244,11 +80971,11 @@ index a07fcfa9ca2..50e6580f6d3 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java -index 8adce9eceff..fa3e192c835 100644 +index 80ebd7b64d0..22b92e861c5 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicLongOpTest.java @@ -22,6 +22,12 @@ @@ -80270,11 +80997,11 @@ index 8adce9eceff..fa3e192c835 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @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 e09c58d8dbd..b65834aaa57 100644 +index e06bbb05098..cc03fc31c99 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopArrayIndexComputeTest.java @@ -22,6 +22,12 @@ @@ -80296,11 +81023,11 @@ index e09c58d8dbd..b65834aaa57 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled */ diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java -index 99f889ae74c..afb4af98afb 100644 +index f1c8fea059b..9cf2023fa7d 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/LoopReductionOpTest.java @@ -21,6 +21,12 @@ @@ -80322,14 +81049,14 @@ index 99f889ae74c..afb4af98afb 100644 * - * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") + * @requires (os.simpleArch == "x64") | (os.simpleArch == "aarch64") | (os.simpleArch == "loongarch64") - * @requires vm.compiler2.enabled & vm.flagless + * @requires vm.compiler2.enabled * */ diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java -index a0dff95a23f..fd0fcbd3a90 100644 +index 8004d34f5ce..1001f48afe6 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java -@@ -21,6 +21,12 @@ +@@ -21,13 +21,19 @@ * questions. */ @@ -80341,8 +81068,7 @@ index a0dff95a23f..fd0fcbd3a90 100644 + /** * @test - * @enablePreview -@@ -28,7 +34,7 @@ + * @bug 8259937 * @summary guarantee(loc != NULL) failed: missing saved register with native invoke * * @requires vm.flavor == "server" @@ -80353,10 +81079,10 @@ index a0dff95a23f..fd0fcbd3a90 100644 * @run main/othervm --enable-native-access=ALL-UNNAMED -XX:+UnlockDiagnosticVMOptions diff --git a/test/hotspot/jtreg/loongson/25064/NUMAHelper.java b/test/hotspot/jtreg/loongson/25064/NUMAHelper.java new file mode 100644 -index 00000000000..ee0c4387eb3 +index 00000000000..40443449bf3 --- /dev/null +++ b/test/hotspot/jtreg/loongson/25064/NUMAHelper.java -@@ -0,0 +1,100 @@ +@@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -80415,8 +81141,7 @@ index 00000000000..ee0c4387eb3 + } + + static OutputAnalyzer invokeJvm(String... args) throws Exception { -+ ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(args); -+ return new OutputAnalyzer(pb.start()); ++ return new OutputAnalyzer(ProcessTools.createTestJvm(args).start()); + } + + static int getNUMANodes() throws Exception { @@ -81603,7 +82328,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..92a4f00c247 +index 00000000000..29c3cebfece --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestLoadLoad.java @@ -0,0 +1,129 @@ @@ -81656,7 +82381,7 @@ index 00000000000..92a4f00c247 + command.add("-XX:+PrintInterpreter"); + command.add("-version"); + -+ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); @@ -81738,7 +82463,7 @@ index 00000000000..92a4f00c247 +} diff --git a/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java b/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java new file mode 100644 -index 00000000000..2bc9ada7ce8 +index 00000000000..a9a8cb39dca --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestNewObjectWithFinal.java @@ -0,0 +1,247 @@ @@ -81814,7 +82539,7 @@ index 00000000000..2bc9ada7ce8 + command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test"); + command.add(Launcher.class.getName()); + -+ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); @@ -81991,7 +82716,7 @@ index 00000000000..2bc9ada7ce8 +} diff --git a/test/hotspot/jtreg/loongson/30358/TestVolatile.java b/test/hotspot/jtreg/loongson/30358/TestVolatile.java new file mode 100644 -index 00000000000..9fefa381c38 +index 00000000000..ebe7ed7329a --- /dev/null +++ b/test/hotspot/jtreg/loongson/30358/TestVolatile.java @@ -0,0 +1,358 @@ @@ -82071,7 +82796,7 @@ index 00000000000..9fefa381c38 + command.add("-XX:CompileCommand=dontinline," + Launcher.class.getName() + "::" + "*"); + command.add(Launcher.class.getName()); + -+ ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); ++ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(command); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + @@ -82420,8 +83145,71 @@ index 00000000000..defa026410b + } + +} +diff --git a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java +index 8a25b1eff88..58044526183 100644 +--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.java ++++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedCPUSpecificClassSpaceReservation.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 + * @summary Test the various CPU-specific reservation schemes +@@ -94,6 +100,19 @@ private static void do_test(boolean CDS) throws IOException { + } + // bits 44..64 + output.shouldContain("reserve_between (range [0x0000100000000000-0xffffffffffffffff)"); ++ } else if (Platform.isLoongArch64()) { ++ output.shouldContain(tryReserveForUnscaled); // unconditionally ++ if (CDS) { ++ output.shouldNotContain(tryReserveForZeroBased); ++ // bits 32..52 ++ output.shouldContain("reserve_between (range [0x0000000100000000-0x0010000000000000)"); ++ } else { ++ output.shouldContain(tryReserveForZeroBased); ++ // bits 32..52, but not lower than zero-based limit ++ output.shouldContain("reserve_between (range [0x0000000800000000-0x0010000000000000)"); ++ } ++ // bits 52..64 ++ output.shouldContain("reserve_between (range [0x0010000000000000-0xffffffffffffffff)"); + } else if (Platform.isS390x()) { + output.shouldContain(tryReserveForUnscaled); // unconditionally + if (CDS) { +diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java b/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java +index 7d7deffdb6e..a0c592a8687 100644 +--- a/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java ++++ b/test/hotspot/jtreg/runtime/ErrorHandling/StackWalkNativeToJava.java +@@ -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. ++ */ ++ + import jdk.test.lib.process.OutputAnalyzer; + import jdk.test.lib.process.ProcessTools; + import jdk.test.lib.Utils; +@@ -33,7 +39,7 @@ + * @test StackWalkNativeToJava + * @bug 8316309 + * @summary Check that walking the stack works fine when going from C++ frame to Java frame. +- * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" ++ * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="loongarch64" + * @requires os.family != "windows" + * @requires vm.flagless + * @library /test/lib diff --git a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java -index 36f74d01b54..02988acca3d 100644 +index e75e6643809..88bd67d6b39 100644 --- a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java +++ b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java @@ -21,6 +21,12 @@ @@ -82437,7 +83225,7 @@ index 36f74d01b54..02988acca3d 100644 /* * @test ReservedStackTest * -@@ -240,7 +246,7 @@ public class ReservedStackTest { +@@ -240,7 +246,7 @@ private static boolean isAlwaysSupportedPlatform() { return Platform.isAix() || (Platform.isLinux() && (Platform.isPPC() || Platform.isS390x() || Platform.isX64() || @@ -82447,7 +83235,7 @@ index 36f74d01b54..02988acca3d 100644 } diff --git a/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java b/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java -index 7bc07d1c9c3..b9d0ba7e4fd 100644 +index a94d9af4c27..0935a4a6517 100644 --- a/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java +++ b/test/hotspot/jtreg/runtime/os/TestTracePageSizes.java @@ -21,6 +21,12 @@ @@ -82489,7 +83277,7 @@ index 5c41565db8d..ec9499d92a9 100644 package MyPackage; /** -@@ -29,7 +35,7 @@ package MyPackage; +@@ -29,7 +35,7 @@ * @summary Verifies that AsyncGetCallTrace is call-able and provides sane information. * @compile ASGCTBaseTest.java * @requires os.family == "linux" @@ -82515,7 +83303,7 @@ index 5d9c3982fb6..f346e763db5 100644 import java.io.OutputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; -@@ -36,7 +42,7 @@ import jdk.test.lib.SA.SATestUtils; +@@ -36,7 +42,7 @@ /** * @test * @requires vm.hasSA @@ -82525,7 +83313,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 5160ccb8e3b..912f551f2a4 100644 +index 6ad3f377706..cefd4e94811 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 @@ @@ -82541,7 +83329,7 @@ index 5160ccb8e3b..912f551f2a4 100644 package ir_framework.tests; import compiler.lib.ir_framework.*; -@@ -215,7 +221,7 @@ public class TestIRMatching { +@@ -215,7 +221,7 @@ public static void main(String[] args) { runCheck(BadFailOnConstraint.create(Membar.class, "membar()", 1, "MemBar")); String cmp; @@ -82567,7 +83355,7 @@ index 16863189500..e2f3a13473b 100644 package nsk.share.jdi; import nsk.share.*; -@@ -520,21 +526,22 @@ class CheckedFeatures { +@@ -520,21 +526,22 @@ protected void checkOptions() { * available only on the Microsoft Windows platform. * " */ @@ -82605,7 +83393,7 @@ index 16863189500..e2f3a13473b 100644 // listening connectors /* -@@ -546,21 +553,22 @@ class CheckedFeatures { +@@ -546,21 +553,22 @@ protected void checkOptions() { * It is available only on the Microsoft Windows platform. * " */ @@ -82643,7 +83431,7 @@ index 16863189500..e2f3a13473b 100644 // launching connectors /* -@@ -575,78 +583,82 @@ class CheckedFeatures { +@@ -575,78 +583,82 @@ protected void checkOptions() { * Windows, the shared memory transport is used. On Linux the socket transport is used. * " */ @@ -82781,10 +83569,10 @@ index 16863189500..e2f3a13473b 100644 } diff --git a/test/jdk/java/foreign/callarranger/TestLoongArch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestLoongArch64CallArranger.java new file mode 100644 -index 00000000000..399cdbb252e +index 00000000000..f4ebd42f612 --- /dev/null +++ b/test/jdk/java/foreign/callarranger/TestLoongArch64CallArranger.java -@@ -0,0 +1,521 @@ +@@ -0,0 +1,520 @@ +/* + * Copyright (c) 2023, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -82811,7 +83599,6 @@ index 00000000000..399cdbb252e + +/* + * @test -+ * @enablePreview + * @requires sun.arch.data.model == "64" + * @compile platform/PlatformLayouts.java + * @modules java.base/jdk.internal.foreign @@ -83307,14 +84094,13 @@ index 00000000000..399cdbb252e + } +} diff --git a/test/jdk/java/foreign/callarranger/platform/PlatformLayouts.java b/test/jdk/java/foreign/callarranger/platform/PlatformLayouts.java -index 1646063fb08..c6d6fa8efb5 100644 +index 48ca23befef..26ebd13e708 100644 --- a/test/jdk/java/foreign/callarranger/platform/PlatformLayouts.java +++ b/test/jdk/java/foreign/callarranger/platform/PlatformLayouts.java -@@ -23,6 +23,13 @@ - * questions. - * +@@ -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 @@ -83324,10 +84110,11 @@ index 1646063fb08..c6d6fa8efb5 100644 package platform; import jdk.internal.foreign.abi.SharedUtils; -@@ -306,4 +313,55 @@ public final class PlatformLayouts { +@@ -303,4 +309,56 @@ private RISCV64() {} + public static final AddressLayout C_POINTER = SharedUtils.C_POINTER; } - ++ + public static final class LoongArch64 { + + // Suppresses default constructor, ensuring non-instantiability. @@ -83380,28 +84167,8 @@ index 1646063fb08..c6d6fa8efb5 100644 + + } } -diff --git a/test/jdk/java/nio/file/Files/CopyAndMove.java b/test/jdk/java/nio/file/Files/CopyAndMove.java -index 8f6e7742356..d871b1873a4 100644 ---- a/test/jdk/java/nio/file/Files/CopyAndMove.java -+++ b/test/jdk/java/nio/file/Files/CopyAndMove.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -909,7 +909,7 @@ public class CopyAndMove { - if (supportsLinks) { - source = createSourceFile(dir1); - link = dir1.resolve("link"); -- createSymbolicLink(link, source); -+ createSymbolicLink(link, source.getFileName()); - target = getTargetFile(dir2); - copyAndVerify(link, target); - delete(link); diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java -index eacfaeb0785..14007ebd5f6 100644 +index b8e9a1736c4..3abafdb93d4 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -31,6 +31,12 @@ @@ -83425,26 +84192,7 @@ index eacfaeb0785..14007ebd5f6 100644 + * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" | os.arch == "s390x" | os.arch== "loongarch64" * @requires vm.debug * @library /test/lib - * @run main/othervm/timeout=1600 -XX:+UseHeavyMonitors -XX:+VerifyHeavyMonitors MapLoops -diff --git a/test/jdk/jdk/internal/util/ArchTest.java b/test/jdk/jdk/internal/util/ArchTest.java -index 1ffc91f77a5..188fbb690f1 100644 ---- a/test/jdk/jdk/internal/util/ArchTest.java -+++ b/test/jdk/jdk/internal/util/ArchTest.java -@@ -20,6 +20,14 @@ - * 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. -+ * -+ */ -+ - import java.util.Locale; - import java.util.stream.Stream; - + * @run main/othervm/timeout=1600 -XX:LockingMode=0 -XX:+VerifyHeavyMonitors MapLoops diff --git a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java b/test/jdk/jdk/jfr/event/os/TestCPUInformation.java index c5166580010..f51a1468754 100644 --- a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java @@ -83462,7 +84210,7 @@ index c5166580010..f51a1468754 100644 package jdk.jfr.event.os; import java.util.List; -@@ -52,8 +58,8 @@ public class TestCPUInformation { +@@ -52,8 +58,8 @@ public static void main(String[] args) throws Throwable { Events.assertField(event, "hwThreads").atLeast(1); Events.assertField(event, "cores").atLeast(1); Events.assertField(event, "sockets").atLeast(1); @@ -83498,7 +84246,7 @@ index 37d770b62a5..1c3df61b8a7 100644 */ import java.net.InetAddress; import java.net.UnknownHostException; -@@ -63,7 +70,7 @@ public class DefaultCaching { +@@ -63,7 +70,7 @@ public static void main(String args[]) throws Exception { test("foo", "10.5.18.22", true, 5); // now delay to see if theclub has expired @@ -83507,37 +84255,11 @@ index 37d770b62a5..1c3df61b8a7 100644 test("foo", "10.5.18.22", true, 5); test("theclub", "129.156.220.1", true, 6); -diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java -index 92c452a69b0..81929957e9d 100644 ---- a/test/jdk/sun/security/pkcs11/PKCS11Test.java -+++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java -@@ -21,6 +21,12 @@ - * questions. - */ - -+/* -+ * This file has been modified by Loongson Technology in 2022, These -+ * modifications are Copyright (c) 2021, 2022, Loongson Technology, and are made -+ * available on the same license terms set forth above. -+ */ -+ - // common infrastructure for SunPKCS11 tests - - import java.io.ByteArrayOutputStream; -@@ -697,6 +703,8 @@ public abstract class PKCS11Test { - "/usr/lib64/" }); - osMap.put("Linux-ppc64-64", new String[] { "/usr/lib64/" }); - osMap.put("Linux-ppc64le-64", new String[] { "/usr/lib64/" }); -+ osMap.put("Linux-loongarch64-64", new String[]{"/usr/lib/loongarch64-linux-gnu/", -+ "/usr/lib64/" }); - osMap.put("Linux-s390x-64", new String[] { "/usr/lib64/" }); - osMap.put("Windows-x86-32", new String[] {}); - osMap.put("Windows-amd64-64", new String[] {}); diff --git a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java -index 355cd8ac200..09ca4547407 100644 +index f8ce856bddd..84b7ecba37f 100644 --- a/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java +++ b/test/lib-test/jdk/test/lib/TestMutuallyExclusivePlatformPredicates.java -@@ -33,6 +33,12 @@ import java.util.HashSet; +@@ -33,6 +33,12 @@ import java.util.List; import java.util.Set; @@ -83550,7 +84272,7 @@ index 355cd8ac200..09ca4547407 100644 /** * @test * @summary Verify that for each group of mutually exclusive predicates defined -@@ -45,7 +51,7 @@ import java.util.Set; +@@ -45,7 +51,7 @@ */ public class TestMutuallyExclusivePlatformPredicates { private static enum MethodGroup { @@ -83560,7 +84282,7 @@ index 355cd8ac200..09ca4547407 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 c58877c6c5e..04e9c095b06 100644 +index 92663c65d0f..311facd8ee1 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -21,6 +21,12 @@ @@ -83576,7 +84298,7 @@ index c58877c6c5e..04e9c095b06 100644 package jdk.test.lib; import java.io.BufferedReader; -@@ -233,6 +239,10 @@ public class Platform { +@@ -234,6 +240,10 @@ public static boolean isX86() { return isArch("(i386)|(x86(?!_64))"); } diff --git a/OpenJDK21U-jdk_x64_linux_hotspot_21.0.3_9.tar.gz b/OpenJDK23U-jdk_aarch64_linux_hotspot_23.0.1_11.tar.gz similarity index 81% rename from OpenJDK21U-jdk_x64_linux_hotspot_21.0.3_9.tar.gz rename to OpenJDK23U-jdk_aarch64_linux_hotspot_23.0.1_11.tar.gz index 99e206e3383cdde55933310df69d4b9dc680a715..97497f21877a27197087695d2e198951f79c5d28 100644 Binary files a/OpenJDK21U-jdk_x64_linux_hotspot_21.0.3_9.tar.gz and b/OpenJDK23U-jdk_aarch64_linux_hotspot_23.0.1_11.tar.gz differ diff --git a/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.3_9.tar.gz b/OpenJDK23U-jdk_x64_linux_hotspot_23.0.1_11.tar.gz similarity index 82% rename from OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.3_9.tar.gz rename to OpenJDK23U-jdk_x64_linux_hotspot_23.0.1_11.tar.gz index 14fdee29b81f5cabf63eb6fe880f3d2ee4d3c3ef..18b1622cde2f556d6916c2fa9429ab40975542bc 100644 Binary files a/OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.3_9.tar.gz and b/OpenJDK23U-jdk_x64_linux_hotspot_23.0.1_11.tar.gz differ diff --git a/downgrade-the-glibc-symver-of-memcpy.patch b/downgrade-the-glibc-symver-of-memcpy.patch index 1be60a1b86210195f65a0245396df3679cb97ada..9ae77270031f1a08c213de0529fb7629d13f8dad 100644 --- a/downgrade-the-glibc-symver-of-memcpy.patch +++ b/downgrade-the-glibc-symver-of-memcpy.patch @@ -5,40 +5,40 @@ Subject: [PATCH] [Huawei] downgrade the glibc symver of memcpy Signed-off-by: Sun Jianye --- - make/common/NativeCompilation.gmk | 9 +++++++++ + make/common/native/Link.gmk | 9 +++++++++ make/hotspot/lib/CompileJvm.gmk | 8 ++++++++ src/hotspot/share/runtime/memcpy.cpp | 20 ++++++++++++++++++++ .../linux/native/applauncher/LinuxPackage.c | 3 +++ 4 files changed, 40 insertions(+) create mode 100644 src/hotspot/share/runtime/memcpy.cpp -diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk +diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk index 1e2b170..4f22e2d 100644 ---- a/make/common/NativeCompilation.gmk -+++ b/make/common/NativeCompilation.gmk -@@ -1102,6 +1102,15 @@ define SetupNativeCompilationBody - endif - endif - -+ # if ldflags contain --wrap=memcpy, add memcpy.o to OBJS -+ ifneq ($$(findstring wrap=memcpy, $$($1_LDFLAGS)$$($1_EXTRA_LDFLAGS)),) -+ ifeq ($$(findstring memcpy$(OBJ_SUFFIX), $$($1_ALL_OBJS)),) -+ $$($1_BUILD_INFO): -+ $(ECHO) 'Adding $(SUPPORT_OUTPUTDIR)/memcpy/memcpy$(OBJ_SUFFIX) to $1_ALL_OBJS' -+ $1_ALL_OBJS += $(SUPPORT_OUTPUTDIR)/memcpy/memcpy$(OBJ_SUFFIX) -+ endif +--- a/make/common/native/Link.gmk ++++ b/make/common/native/Link.gmk +@@ -131,6 +131,15 @@ define SetupNativeCompilationBody + $1_CODESIGN_OPTS := - + endif + ++ # if ldflags contain --wrap=memcpy, add memcpy.o to OBJS ++ ifneq ($$(findstring wrap=memcpy, $$($1_LDFLAGS)$$($1_EXTRA_LDFLAGS)),) ++ ifeq ($$(findstring memcpy$(OBJ_SUFFIX), $$($1_ALL_OBJS)),) ++ $$($1_BUILD_INFO): ++ $(ECHO) 'Adding $(SUPPORT_OUTPUTDIR)/memcpy/memcpy$(OBJ_SUFFIX) to $1_ALL_OBJS' ++ $1_ALL_OBJS += $(SUPPORT_OUTPUTDIR)/memcpy/memcpy$(OBJ_SUFFIX) + endif ++ endif + - $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ - $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ - $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ + $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) \ + $$($1_EXTRA_LDFLAGS) $$($1_LIBS) $$($1_EXTRA_LIBS) \ + $$($1_DEBUGINFO_FILES) $$($1_STRIPFLAGS) diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 65edd04..d5b689e 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk -@@ -204,6 +204,14 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \ - STATIC_LIB_EXCLUDE_OBJS := $(LIBJVM_STATIC_EXCLUDE_OBJS), \ - )) +@@ -254,6 +254,14 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \ + $(BUILD_LIBJVM_TARGET): $(WIN_EXPORT_FILE) + endif +MEMCPY_OBJECT_FILE := $(JVM_OUTPUTDIR)/objs/memcpy$(OBJ_SUFFIX) + diff --git a/jdk-updates-jdk22u-jdk-22+36.tar.gz b/jdk-updates-jdk23u-jdk-23.0.1+11.tar.gz similarity index 80% rename from jdk-updates-jdk22u-jdk-22+36.tar.gz rename to jdk-updates-jdk23u-jdk-23.0.1+11.tar.gz index 182423ff019d0a51921cbc87d42515ff6a0ad1f4..117daae75c872e112ff72ec503ddbc53dd39c4ba 100644 Binary files a/jdk-updates-jdk22u-jdk-22+36.tar.gz and b/jdk-updates-jdk23u-jdk-23.0.1+11.tar.gz differ diff --git a/openjdk-latest.spec b/openjdk-latest.spec index 59b0adfb6514e859a26645e6f488290b10f48eee..ae0b344ad715c5a0faa8818dd4f4134141b0c5ec 100644 --- a/openjdk-latest.spec +++ b/openjdk-latest.spec @@ -72,7 +72,7 @@ %global is_system_jdk 0 %global aarch64 aarch64 arm64 armv8 -%global jit_arches x86_64 %{aarch64} riscv64 loongarch64 +%global jit_arches x86_64 %{aarch64} riscv64 loongarch64 ppc64le %global aot_arches x86_64 %{aarch64} # Set of architectures for which java has short vector math library (libsvml.so) @@ -154,15 +154,15 @@ # New Version-String scheme-style defines # If you bump majorver, you must bump also vendor_version_string -%global majorver 22 +%global majorver 23 # Used via new version scheme. JDK 19 was # GA'ed in March 2022 => 22.3 %global vendor_version_string BiSheng -%global securityver 0 +%global securityver 1 # buildjdkver is usually same as %%{majorver}, # but in time of bootstrap of next jdk, it is majorver-1, # and this it is better to change it here, on single place -%global buildjdkver 22 +%global buildjdkver 23 # We don't add any LTS designator for STS packages (Fedora and EPEL). # We need to explicitly exclude EPEL as it would have the %%{rhel} macro defined. %if 0%{?rhel} && !0%{?epel} @@ -178,7 +178,7 @@ %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global minorver 0 -%global buildver 36 +%global buildver 11 %global rpmrelease 1 # 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 @@ -542,7 +542,6 @@ exit 0 %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libjimage.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libjsound.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/liblcms.so -%{_jvmdir}/%{sdkdir -- %{?1}}/lib/lible.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libmanagement.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libmanagement_agent.so %{_jvmdir}/%{sdkdir -- %{?1}}/lib/libmanagement_ext.so @@ -601,6 +600,7 @@ exit 0 # these are config templates, thus not config-noreplace %config %{etcjavadir -- %{?1}}/conf/management/jmxremote.password.template %config %{etcjavadir -- %{?1}}/conf/sdp/sdp.conf.template +%config %{etcjavadir -- %{?1}}/conf/jaxp-strict.properties.template %config(noreplace) %{etcjavadir -- %{?1}}/conf/management/management.properties %config(noreplace) %{etcjavadir -- %{?1}}/conf/net.properties %config(noreplace) %{etcjavadir -- %{?1}}/conf/sound.properties @@ -898,7 +898,7 @@ Name: java-latest-%{origin} Version: %{newjavaver}.%{buildver} # This package needs `.rolling` as part of Release so as to not conflict on install with # java-X-openjdk. I.e. when latest rolling release is also an LTS release packaged as -Release: 0 +Release: 1 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages @@ -927,15 +927,15 @@ Summary: %{origin_nice} Runtime Environment %{majorver} # The test code includes copies of NSS under the Mozilla Public License v2.0 # The PCSClite headers are under a BSD with advertising license # The elliptic curve cryptography (ECC) source code is licensed under the LGPLv2.1 or any later version -License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA +License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA-MD URL: http://openjdk.java.net/ # to regenerate source0 (jdk) and source8 (jdk's taspets) run update_package.sh # update_package.sh contains hard-coded repos, revisions, tags, and projects to regenerate the source archives Source0: jdk-updates-jdk%{majorver}u-jdk-%{filever}+%{buildver}.tar.gz -Source1: OpenJDK21U-jdk_aarch64_linux_hotspot_21.0.3_9.tar.gz -Source2: OpenJDK21U-jdk_x64_linux_hotspot_21.0.3_9.tar.gz +Source1: OpenJDK23U-jdk_aarch64_linux_hotspot_23.0.1_11.tar.gz +Source2: OpenJDK23U-jdk_x64_linux_hotspot_23.0.1_11.tar.gz Source8: systemtap_3.2_tapsets_hg-icedtea8-9d464368e06d.tar.xz # Desktop files. Adapted from IcedTea @@ -980,12 +980,8 @@ Patch3: rh649512-remove_uses_of_far_in_jpeg_libjpeg_turbo_1_4_compat_for_jdk10_a Patch7: downgrade-the-glibc-symver-of-memcpy.patch Patch8: downgrade-the-glibc-symver-of-log2f-posix_spawn.patch -############################################ -# -# RISC-V specific patches -# -############################################ -Patch2000: 8316859-RISC-V-Disable-detection-of-V-through-HWCAP.patch +# 23.0.1 +Patch9: 8332854-Unable-to-build-openjdk-with-with-harfbuzz=system.patch ############################################ # @@ -1223,16 +1219,11 @@ pushd %{top_level_dir_name} %patch3 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 popd # openjdk %patch1000 -%ifarch riscv64 -pushd %{top_level_dir_name} -%patch2000 -p1 -popd -%endif - %ifarch loongarch64 pushd %{top_level_dir_name} %patch3000 -p1 @@ -1345,14 +1336,16 @@ ARCH=$(uname -m) BOOTJDKPATH=/usr/lib/jvm/java-%{buildjdkver}-openjdk if [ "$ARCH" = "x86_64" ]; then tar -xf %{SOURCE2} - BOOTJDKPATH=$PWD/jdk-21.0.3+9 + BOOTJDKPATH=$PWD/jdk-23.0.1+11 elif [ "$ARCH" = "aarch64" ]; then tar -xf %{SOURCE1} - BOOTJDKPATH=$PWD/jdk-21.0.3+9 + BOOTJDKPATH=$PWD/jdk-23.0.1+11 elif [ "$ARCH" = "riscv64" ]; then : elif [ "$ARCH" = "loongarch64" ]; then : +elif [ "$ARCH" = "ppc64le" ]; then + : else echo " Failed to set BOOTJDKPATH " exit 18 @@ -1457,7 +1450,7 @@ $JAVA_HOME/bin/java $(echo $(basename %{SOURCE14})|sed "s|\.java||") # Check debug symbols are present and can identify code find "$JAVA_HOME" -iname '*.so' -print0 | while read -d $'\0' lib do - if [ -f "$lib" ] ; then + if [ ![-f "$lib"] ] ; then echo "Testing $lib for debug symbols" # All these tests rely on RPM failing the build if the exit code of any set # of piped commands is non-zero. @@ -1647,7 +1640,12 @@ done -- (copy_jdk_configs from %%{_libexecdir} used) or not copied at all local posix = require "posix" -local debug = false +if (os.getenv("debug") == "true") then + debug = true; + print("cjc: in spec debug is on") +else + debug = false; +end SOURCE1 = "%{rpm_state_dir}/copy_jdk_configs.lua" SOURCE2 = "%{_libexecdir}/copy_jdk_configs.lua" @@ -1676,8 +1674,10 @@ else end end -- run content of included file with fake args -arg = {"--currentjvm", "%{uniquesuffix %{nil}}", "--jvmdir", "%{_jvmdir %{nil}}", "--origname", "%{name}", "--origjavaver", "%{javaver}", "--arch", "%{_arch}", "--temp", "%{rpm_state_dir}/%{name}.%{_arch}"} -require "copy_jdk_configs.lua" +arg = nil; -- it is better to null the arg up, no meter if they exists or not, and use cjc as module in unified way, instead of relaying on "main" method during require "copy_jdk_configs.lua" +cjc = require "copy_jdk_configs.lua" +args = {"--currentjvm", "%{uniquesuffix %{nil}}", "--jvmdir", "%{_jvmdir %{nil}}", "--origname", "%{name}", "--origjavaver", "%{javaver}", "--arch", "%{_arch}", "--temp", "%{rpm_state_dir}/%{name}.%{_arch}"} +cjc.mainProgram(args) -- the returns from copy_jdk_configs.lua should not affect this 'main', so it should run under all circumstances, except fatal error %post %{post_script %{nil}} @@ -1802,6 +1802,28 @@ require "copy_jdk_configs.lua" %changelog +* Fri Nov 22 2024 Dingli Zhang - 1:23.0.1.11-1 +- Modify bootjdk for riscv64 +- Backport JDK-8332854 + +* Tue Nov 19 2024 neu-mobi - 1:23.0.1.11-0 +- update to jdk23.0.1+11 +- remove some redundant patches & fix changelog + +* Tue Aug 6 2024 kuenking111 - 1:22.0.2.9-rolling +- update to jdk22.0.2+9 + +* Fri Jul 12 2024 Dingli Zhang - 1:22.0.0.36-3 +- Remove Backport JDK-8316859 for riscv64 +- Fix typo in changelog +- Add bootjdk for riscv64 + +* Tue Jun 25 2024 peng.zou - 1:22.0.0.36-2 +- Add support for ppc64le + +* Fri Jun 21 2024 aoqi - 1:22.0.0.36-1 +- update to jdk22+36 for loongarch64 + * Wed Jun 05 2024 Autistic_boyya - 1:22.0.0.36-rolling - update to jdk22+36 diff --git a/pr3183-rh1340845-support_system_crypto_policy.patch b/pr3183-rh1340845-support_system_crypto_policy.patch deleted file mode 100644 index 9ca3dc6eb9149d4f085844ca4147402a978ce925..0000000000000000000000000000000000000000 --- a/pr3183-rh1340845-support_system_crypto_policy.patch +++ /dev/null @@ -1,87 +0,0 @@ - -# HG changeset patch -# User andrew -# Date 1478057514 0 -# Node ID 1c4d5cb2096ae55106111da200b0bcad304f650c -# Parent 3d53f19b48384e5252f4ec8891f7a3a82d77af2a -diff -r 3d53f19b4838 -r 1c4d5cb2096a src/java.base/share/classes/java/security/Security.java ---- a/src/java.base/share/classes/java/security/Security.java Wed Oct 26 03:51:39 2016 +0100 -+++ b/src/java.base/share/classes/java/security/Security.java Wed Nov 02 03:31:54 2016 +0000 -@@ -43,6 +43,9 @@ - * implementation-specific location, which is typically the properties file - * {@code conf/security/java.security} in the Java installation directory. - * -+ *

Additional default values of security properties are read from a -+ * system-specific location, if available.

-+ * - * @author Benjamin Renaud - * @since 1.1 - */ -@@ -52,6 +55,10 @@ - private static final Debug sdebug = - Debug.getInstance("properties"); - -+ /* System property file*/ -+ private static final String SYSTEM_PROPERTIES = -+ "/etc/crypto-policies/back-ends/java.config"; -+ - /* The java.security properties */ - private static Properties props; - -@@ -93,6 +100,7 @@ - if (sdebug != null) { - sdebug.println("reading security properties file: " + - propFile); -+ sdebug.println(props.toString()); - } - } catch (IOException e) { - if (sdebug != null) { -@@ -114,6 +122,31 @@ - } - - if ("true".equalsIgnoreCase(props.getProperty -+ ("security.useSystemPropertiesFile"))) { -+ -+ // now load the system file, if it exists, so its values -+ // will win if they conflict with the earlier values -+ try (BufferedInputStream bis = -+ new BufferedInputStream(new FileInputStream(SYSTEM_PROPERTIES))) { -+ props.load(bis); -+ loadedProps = true; -+ -+ if (sdebug != null) { -+ sdebug.println("reading system security properties file " + -+ SYSTEM_PROPERTIES); -+ sdebug.println(props.toString()); -+ } -+ } catch (IOException e) { -+ if (sdebug != null) { -+ sdebug.println -+ ("unable to load security properties from " + -+ SYSTEM_PROPERTIES); -+ e.printStackTrace(); -+ } -+ } -+ } -+ -+ if ("true".equalsIgnoreCase(props.getProperty - ("security.overridePropertiesFile"))) { - - String extraPropFile = System.getProperty -diff -r 3d53f19b4838 -r 1c4d5cb2096a src/java.base/share/conf/security/java.security ---- a/src/java.base/share/conf/security/java.security Wed Oct 26 03:51:39 2016 +0100 -+++ b/src/java.base/share/conf/security/java.security Wed Nov 02 03:31:54 2016 +0000 -@@ -276,6 +276,13 @@ - security.overridePropertiesFile=true - - # -+# Determines whether this properties file will be appended to -+# using the system properties file stored at -+# /etc/crypto-policies/back-ends/java.config -+# -+security.useSystemPropertiesFile=true -+ -+# - # Determines the default key and trust manager factory algorithms for - # the javax.net.ssl package. - # diff --git a/rh1684077-openjdk_should_depend_on_pcsc-lite-libs_instead_of_pcsc-lite-devel.patch b/rh1684077-openjdk_should_depend_on_pcsc-lite-libs_instead_of_pcsc-lite-devel.patch deleted file mode 100644 index 4c1476fe29737d9ec41aa1558ae634ac89967408..0000000000000000000000000000000000000000 --- a/rh1684077-openjdk_should_depend_on_pcsc-lite-libs_instead_of_pcsc-lite-devel.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff --git a/openjdk/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java b/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java -index bacff32efbc..ff7b3dcc81c 100644 ---- openjdk/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java -+++ openjdk/src/java.smartcardio/unix/classes/sun/security/smartcardio/PlatformPCSC.java -@@ -46,8 +46,8 @@ class PlatformPCSC { - - private static final String PROP_NAME = "sun.security.smartcardio.library"; - -- private static final String LIB1 = "/usr/$LIBISA/libpcsclite.so"; -- private static final String LIB2 = "/usr/local/$LIBISA/libpcsclite.so"; -+ private static final String LIB1 = "/usr/$LIBISA/libpcsclite.so.1"; -+ private static final String LIB2 = "/usr/local/$LIBISA/libpcsclite.so.1"; - private static final String PCSC_FRAMEWORK = "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"; - - PlatformPCSC() {