diff --git a/Add-riscv64-support.patch b/Add-riscv64-support.patch index 59017ae..7e2d50c 100644 --- a/Add-riscv64-support.patch +++ b/Add-riscv64-support.patch @@ -1,346 +1,204 @@ -From dfa792539047c39d0d25244265bc8368163d5768 Mon Sep 17 00:00:00 2001 -From: Fei Yang -Date: Thu, 24 Mar 2022 09:22:46 +0000 -Subject: [PATCH 001/140] Cherry-picked JDK-8276799: initial load of RISC-V - backend (cannot pass compilation) - ---- - make/autoconf/build-aux/config.guess | 2 +- - make/autoconf/hotspot.m4 | 3 +- - make/autoconf/libraries.m4 | 8 +- - make/autoconf/platform.m4 | 6 +- - make/hotspot/gensrc/GensrcAdlc.gmk | 9 +- - .../cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 6 +- - src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp | 7 +- - src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp | 8 +- - .../cpu/riscv/abstractInterpreter_riscv.cpp | 177 + - src/hotspot/cpu/riscv/assembler_riscv.cpp | 372 + - src/hotspot/cpu/riscv/assembler_riscv.hpp | 3047 +++++ - .../cpu/riscv/assembler_riscv.inline.hpp | 47 + - src/hotspot/cpu/riscv/bytes_riscv.hpp | 167 + - src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 353 + - src/hotspot/cpu/riscv/c1_Defs_riscv.hpp | 84 + - .../cpu/riscv/c1_FpuStackSim_riscv.cpp | 30 + - .../cpu/riscv/c1_FpuStackSim_riscv.hpp | 32 + - src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp | 388 + - src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp | 148 + - .../cpu/riscv/c1_LIRAssembler_arith_riscv.cpp | 281 + - .../cpu/riscv/c1_LIRAssembler_arith_riscv.hpp | 37 + - .../riscv/c1_LIRAssembler_arraycopy_riscv.cpp | 388 + - .../riscv/c1_LIRAssembler_arraycopy_riscv.hpp | 52 + - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 2267 ++++ - .../cpu/riscv/c1_LIRAssembler_riscv.hpp | 132 + - .../cpu/riscv/c1_LIRGenerator_riscv.cpp | 1075 ++ - src/hotspot/cpu/riscv/c1_LIR_riscv.cpp | 55 + - src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp | 33 + - src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp | 83 + - .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 432 + - .../cpu/riscv/c1_MacroAssembler_riscv.hpp | 120 + - src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 1172 ++ - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 65 + - .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 1646 +++ - .../cpu/riscv/c2_MacroAssembler_riscv.hpp | 193 + - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 83 + - src/hotspot/cpu/riscv/c2_init_riscv.cpp | 38 + - .../riscv/c2_safepointPollStubTable_riscv.cpp | 47 + - src/hotspot/cpu/riscv/codeBuffer_riscv.hpp | 36 + - src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 149 + - src/hotspot/cpu/riscv/copy_riscv.hpp | 136 + - src/hotspot/cpu/riscv/disassembler_riscv.hpp | 58 + - .../cpu/riscv/foreign_globals_riscv.cpp | 44 + - .../cpu/riscv/foreign_globals_riscv.hpp | 32 + - src/hotspot/cpu/riscv/frame_riscv.cpp | 697 + - src/hotspot/cpu/riscv/frame_riscv.hpp | 202 + - src/hotspot/cpu/riscv/frame_riscv.inline.hpp | 248 + - .../gc/g1/g1BarrierSetAssembler_riscv.cpp | 484 + - .../gc/g1/g1BarrierSetAssembler_riscv.hpp | 78 + - .../cpu/riscv/gc/g1/g1Globals_riscv.hpp | 31 + - .../gc/shared/barrierSetAssembler_riscv.cpp | 302 + - .../gc/shared/barrierSetAssembler_riscv.hpp | 79 + - .../gc/shared/barrierSetNMethod_riscv.cpp | 171 + - .../cardTableBarrierSetAssembler_riscv.cpp | 111 + - .../cardTableBarrierSetAssembler_riscv.hpp | 42 + - .../modRefBarrierSetAssembler_riscv.cpp | 55 + - .../modRefBarrierSetAssembler_riscv.hpp | 55 + - .../c1/shenandoahBarrierSetC1_riscv.cpp | 117 + - .../shenandoahBarrierSetAssembler_riscv.cpp | 712 ++ - .../shenandoahBarrierSetAssembler_riscv.hpp | 88 + - .../riscv/gc/shenandoah/shenandoah_riscv64.ad | 285 + - .../riscv/gc/z/zBarrierSetAssembler_riscv.cpp | 441 + - .../riscv/gc/z/zBarrierSetAssembler_riscv.hpp | 101 + - src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp | 212 + - src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp | 36 + - src/hotspot/cpu/riscv/gc/z/z_riscv64.ad | 233 + - .../cpu/riscv/globalDefinitions_riscv.hpp | 52 + - src/hotspot/cpu/riscv/globals_riscv.hpp | 99 + - src/hotspot/cpu/riscv/icBuffer_riscv.cpp | 79 + - src/hotspot/cpu/riscv/icache_riscv.cpp | 51 + - src/hotspot/cpu/riscv/icache_riscv.hpp | 42 + - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 1940 +++ - src/hotspot/cpu/riscv/interp_masm_riscv.hpp | 285 + - src/hotspot/cpu/riscv/interpreterRT_riscv.cpp | 295 + - src/hotspot/cpu/riscv/interpreterRT_riscv.hpp | 68 + - .../cpu/riscv/javaFrameAnchor_riscv.hpp | 86 + - .../cpu/riscv/jniFastGetField_riscv.cpp | 214 + - src/hotspot/cpu/riscv/jniTypes_riscv.hpp | 106 + - .../cpu/riscv/macroAssembler_riscv.cpp | 4016 ++++++ - .../cpu/riscv/macroAssembler_riscv.hpp | 858 ++ - .../cpu/riscv/macroAssembler_riscv.inline.hpp | 31 + - src/hotspot/cpu/riscv/matcher_riscv.hpp | 169 + - src/hotspot/cpu/riscv/methodHandles_riscv.cpp | 461 + - src/hotspot/cpu/riscv/methodHandles_riscv.hpp | 57 + - src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 429 + - src/hotspot/cpu/riscv/nativeInst_riscv.hpp | 572 + - src/hotspot/cpu/riscv/registerMap_riscv.cpp | 45 + - src/hotspot/cpu/riscv/registerMap_riscv.hpp | 43 + - src/hotspot/cpu/riscv/register_riscv.cpp | 73 + - src/hotspot/cpu/riscv/register_riscv.hpp | 324 + - src/hotspot/cpu/riscv/relocInfo_riscv.cpp | 113 + - src/hotspot/cpu/riscv/relocInfo_riscv.hpp | 44 + - src/hotspot/cpu/riscv/riscv.ad | 10611 ++++++++++++++++ - src/hotspot/cpu/riscv/riscv_b.ad | 527 + - src/hotspot/cpu/riscv/riscv_v.ad | 2065 +++ - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 2761 ++++ - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 3864 ++++++ - src/hotspot/cpu/riscv/stubRoutines_riscv.cpp | 58 + - src/hotspot/cpu/riscv/stubRoutines_riscv.hpp | 161 + - .../templateInterpreterGenerator_riscv.cpp | 1794 +++ - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 3951 ++++++ - src/hotspot/cpu/riscv/templateTable_riscv.hpp | 42 + - .../riscv/universalNativeInvoker_riscv.cpp | 33 + - .../cpu/riscv/universalUpcallHandle_riscv.cpp | 42 + - src/hotspot/cpu/riscv/vmStructs_riscv.hpp | 42 + - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 230 + - src/hotspot/cpu/riscv/vm_version_riscv.hpp | 72 + - src/hotspot/cpu/riscv/vmreg_riscv.cpp | 64 + - src/hotspot/cpu/riscv/vmreg_riscv.hpp | 68 + - src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp | 46 + - src/hotspot/cpu/riscv/vtableStubs_riscv.cpp | 260 + - src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp | 9 +- - src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp | 7 +- - src/hotspot/os/linux/os_linux.cpp | 2 + - .../linux_riscv/assembler_linux_riscv.cpp | 26 + - .../os_cpu/linux_riscv/atomic_linux_riscv.hpp | 134 + - .../os_cpu/linux_riscv/bytes_linux_riscv.hpp | 45 + - .../os_cpu/linux_riscv/copy_linux_riscv.hpp | 31 + - .../linux_riscv/gc/z/zSyscall_linux_riscv.hpp | 42 + - .../linux_riscv/globals_linux_riscv.hpp | 43 + - .../linux_riscv/orderAccess_linux_riscv.hpp | 63 + - .../os_cpu/linux_riscv/os_linux_riscv.cpp | 466 + - .../os_cpu/linux_riscv/os_linux_riscv.hpp | 59 + - .../prefetch_linux_riscv.inline.hpp | 38 + - .../os_cpu/linux_riscv/thread_linux_riscv.cpp | 92 + - .../os_cpu/linux_riscv/thread_linux_riscv.hpp | 48 + - .../linux_riscv/vmStructs_linux_riscv.hpp | 55 + - .../linux_riscv/vm_version_linux_riscv.cpp | 118 + - src/hotspot/share/c1/c1_LIR.cpp | 112 +- - src/hotspot/share/c1/c1_LIR.hpp | 209 +- - src/hotspot/share/c1/c1_LIRAssembler.cpp | 15 +- - src/hotspot/share/c1/c1_LIRAssembler.hpp | 5 +- - src/hotspot/share/c1/c1_LinearScan.cpp | 18 +- - .../gc/shenandoah/shenandoahArguments.cpp | 4 +- - src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp | 4 +- - .../share/jfr/utilities/jfrBigEndian.hpp | 2 +- - src/hotspot/share/opto/regmask.hpp | 2 +- - .../share/runtime/abstract_vm_version.cpp | 3 +- - src/hotspot/share/runtime/synchronizer.cpp | 2 +- - src/hotspot/share/runtime/thread.hpp | 2 +- - src/hotspot/share/runtime/thread.inline.hpp | 4 +- - src/hotspot/share/utilities/macros.hpp | 26 + - .../native/libsaproc/LinuxDebuggerLocal.c | 49 +- - .../linux/native/libsaproc/libproc.h | 4 +- - .../classes/sun/jvm/hotspot/HotSpotAgent.java | 3 + - .../debugger/MachineDescriptionRISCV64.java | 40 + - .../debugger/linux/LinuxCDebugger.java | 13 +- - .../linux/riscv64/LinuxRISCV64CFrame.java | 90 + - .../riscv64/LinuxRISCV64ThreadContext.java | 48 + - .../proc/riscv64/ProcRISCV64Thread.java | 88 + - .../riscv64/ProcRISCV64ThreadContext.java | 48 + - .../riscv64/ProcRISCV64ThreadFactory.java | 46 + - .../remote/riscv64/RemoteRISCV64Thread.java | 55 + - .../riscv64/RemoteRISCV64ThreadContext.java | 48 + - .../riscv64/RemoteRISCV64ThreadFactory.java | 46 + - .../debugger/risv64/RISCV64ThreadContext.java | 172 + - .../sun/jvm/hotspot/runtime/Threads.java | 5 +- - .../LinuxRISCV64JavaThreadPDAccess.java | 134 + - .../riscv64/RISCV64CurrentFrameGuess.java | 223 + - .../hotspot/runtime/riscv64/RISCV64Frame.java | 556 + - .../riscv64/RISCV64JavaCallWrapper.java | 61 + - .../runtime/riscv64/RISCV64RegisterMap.java | 53 + - .../jvm/hotspot/utilities/PlatformInfo.java | 4 +- - test/hotspot/jtreg/compiler/c2/TestBit.java | 7 +- - ...eSHA1IntrinsicsOptionOnUnsupportedCPU.java | 5 +- - ...HA256IntrinsicsOptionOnUnsupportedCPU.java | 5 +- - ...HA512IntrinsicsOptionOnUnsupportedCPU.java | 5 +- - .../cli/TestUseSHAOptionOnUnsupportedCPU.java | 5 +- - .../testcases/GenericTestCaseForOtherCPU.java | 11 +- - ...nericTestCaseForUnsupportedRISCV64CPU.java | 115 + - .../loopopts/superword/ProdRed_Double.java | 4 +- - .../loopopts/superword/ProdRed_Float.java | 4 +- - .../loopopts/superword/ProdRed_Int.java | 4 +- - .../loopopts/superword/ReductionPerf.java | 4 +- - .../superword/SumRedAbsNeg_Double.java | 4 +- - .../superword/SumRedAbsNeg_Float.java | 4 +- - .../loopopts/superword/SumRedSqrt_Double.java | 4 +- - .../loopopts/superword/SumRed_Double.java | 4 +- - .../loopopts/superword/SumRed_Float.java | 4 +- - .../loopopts/superword/SumRed_Int.java | 4 +- - .../sha/predicate/IntrinsicPredicates.java | 11 +- - .../NMT/CheckForProperDetailStackTrace.java | 4 +- - .../ReservedStack/ReservedStackTest.java | 4 +- - .../HeapMonitorEventsForTwoThreadsTest.java | 1 - - ...stMutuallyExclusivePlatformPredicates.java | 2 +- - .../jdk/jfr/event/os/TestCPUInformation.java | 6 +- - test/lib/jdk/test/lib/Platform.java | 4 + - 187 files changed, 59079 insertions(+), 189 deletions(-) - create mode 100644 src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/assembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/assembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/assembler_riscv.inline.hpp - create mode 100644 src/hotspot/cpu/riscv/bytes_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_Defs_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LIR_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c1_globals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c2_globals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/c2_init_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/codeBuffer_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/compiledIC_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/copy_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/disassembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/foreign_globals_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/foreign_globals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/frame_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/frame_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/frame_riscv.inline.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad - create mode 100644 src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/gc/z/z_riscv64.ad - create mode 100644 src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/globals_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/icBuffer_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/icache_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/icache_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/interp_masm_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/interp_masm_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/interpreterRT_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/interpreterRT_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/jniTypes_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/macroAssembler_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/macroAssembler_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp - create mode 100644 src/hotspot/cpu/riscv/matcher_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/methodHandles_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/methodHandles_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/nativeInst_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/nativeInst_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/registerMap_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/registerMap_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/register_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/register_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/relocInfo_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/relocInfo_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/riscv.ad - create mode 100644 src/hotspot/cpu/riscv/riscv_b.ad - create mode 100644 src/hotspot/cpu/riscv/riscv_v.ad - create mode 100644 src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/stubGenerator_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/stubRoutines_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/stubRoutines_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/templateTable_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/templateTable_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/vmStructs_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/vm_version_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/vm_version_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/vmreg_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/vmreg_riscv.hpp - create mode 100644 src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp - create mode 100644 src/hotspot/cpu/riscv/vtableStubs_riscv.cpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/risv64/RISCV64ThreadContext.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java - create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java - create mode 100644 test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java - -diff --git a/make/autoconf/build-aux/config.guess b/make/autoconf/build-aux/config.guess -index a88a9adec3f..15111d827ab 100644 ---- a/make/autoconf/build-aux/config.guess -+++ b/make/autoconf/build-aux/config.guess +diff --git a/.github/workflows/build-cross-compile.yml b/.github/workflows/build-cross-compile.yml +index 385b097b9f..4eebe79871 100644 +--- a/.github/workflows/build-cross-compile.yml ++++ b/.github/workflows/build-cross-compile.yml +@@ -54,28 +54,39 @@ jobs: + - arm + - s390x + - ppc64le ++ - riscv64 + include: + - target-cpu: aarch64 + gnu-arch: aarch64 + debian-arch: arm64 + debian-repository: https://httpredir.debian.org/debian/ + debian-version: bullseye ++ tolerate-sysroot-errors: false + - target-cpu: arm + gnu-arch: arm + debian-arch: armhf + debian-repository: https://httpredir.debian.org/debian/ + debian-version: bullseye ++ tolerate-sysroot-errors: false + gnu-abi: eabihf + - target-cpu: s390x + gnu-arch: s390x + debian-arch: s390x + debian-repository: https://httpredir.debian.org/debian/ + debian-version: bullseye ++ tolerate-sysroot-errors: false + - target-cpu: ppc64le + gnu-arch: powerpc64le + debian-arch: ppc64el + debian-repository: https://httpredir.debian.org/debian/ + debian-version: bullseye ++ tolerate-sysroot-errors: false ++ - target-cpu: riscv64 ++ gnu-arch: riscv64 ++ debian-arch: riscv64 ++ debian-repository: https://snapshot.debian.org/archive/debian/20240228T034848Z/ ++ debian-version: sid ++ tolerate-sysroot-errors: true + + steps: + - name: 'Checkout the JDK source' +@@ -113,6 +124,7 @@ jobs: + if: steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Create sysroot' ++ id: create-sysroot + run: > + sudo debootstrap + --arch=${{ matrix.debian-arch }} +@@ -123,6 +135,7 @@ jobs: + ${{ matrix.debian-version }} + sysroot + ${{ matrix.debian-repository }} ++ continue-on-error: ${{ matrix.tolerate-sysroot-errors }} + if: steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Prepare sysroot' +@@ -134,7 +147,12 @@ jobs: + rm -rf sysroot/usr/{sbin,bin,share} + rm -rf sysroot/usr/lib/{apt,gcc,udev,systemd} + rm -rf sysroot/usr/libexec/gcc +- if: steps.get-cached-sysroot.outputs.cache-hit != 'true' ++ if: steps.create-sysroot.outcome == 'success' && steps.get-cached-sysroot.outputs.cache-hit != 'true' ++ ++ - name: 'Remove broken sysroot' ++ run: | ++ sudo rm -rf sysroot/ ++ if: steps.create-sysroot.outcome != 'success' && steps.get-cached-sysroot.outputs.cache-hit != 'true' + + - name: 'Configure' + run: > +@@ -153,6 +171,7 @@ jobs: + echo "Dumping config.log:" && + cat config.log && + exit 1) ++ if: steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true' + + - name: 'Build' + id: build +@@ -160,3 +179,4 @@ jobs: + with: + make-target: 'hotspot ${{ inputs.make-arguments }}' + platform: linux-${{ matrix.target-cpu }} ++ if: steps.create-sysroot.outcome == 'success' || steps.get-cached-sysroot.outputs.cache-hit == 'true' +diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml +index 4186c451b7..678f5a038e 100644 +--- a/.github/workflows/build-macos.yml ++++ b/.github/workflows/build-macos.yml +@@ -55,7 +55,7 @@ on: + jobs: + build-macos: + name: build +- runs-on: macos-13 ++ runs-on: macos-12 + + strategy: + fail-fast: false +diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml +index 78a8e1e0d4..46cae3afbf 100644 +--- a/.github/workflows/main.yml ++++ b/.github/workflows/main.yml +@@ -223,7 +223,7 @@ jobs: + uses: ./.github/workflows/build-macos.yml + with: + platform: macos-x64 +- xcode-toolset-version: '14.3.1' ++ xcode-toolset-version: '13.4.1' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + if: needs.select.outputs.macos-x64 == 'true' +@@ -234,7 +234,7 @@ jobs: + uses: ./.github/workflows/build-macos.yml + with: + platform: macos-aarch64 +- xcode-toolset-version: '14.3.1' ++ xcode-toolset-version: '13.4.1' + extra-conf-options: '--openjdk-target=aarch64-apple-darwin' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} +@@ -298,7 +298,7 @@ jobs: + with: + platform: macos-x64 + bootjdk-platform: macos-x64 +- runs-on: macos-13 ++ runs-on: macos-12 + + test-windows-x64: + name: windows-x64 +@@ -341,7 +341,7 @@ jobs: + -H 'Accept: application/vnd.github+json' \ + -H 'Authorization: Bearer ${{ github.token }}' \ + -H 'X-GitHub-Api-Version: 2022-11-28' \ +- '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts')" ++ '${{ github.api_url }}/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts?per_page=100')" + BUNDLE_ARTIFACT_IDS="$(echo "$ALL_ARTIFACT_IDS" | jq -r -c '.artifacts | map(select(.name|startswith("bundles-"))) | .[].id')" + for id in $BUNDLE_ARTIFACT_IDS; do + echo "Removing $id" +diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml +index c3560f2135..dacf8eaba1 100644 +--- a/.github/workflows/test.yml ++++ b/.github/workflows/test.yml +@@ -127,7 +127,7 @@ jobs: + run: | + # On macOS we need to install some dependencies for testing + brew install make +- sudo xcode-select --switch /Applications/Xcode_14.3.1.app/Contents/Developer ++ sudo xcode-select --switch /Applications/Xcode_13.4.1.app/Contents/Developer + # This will make GNU make available as 'make' and not only as 'gmake' + echo '/usr/local/opt/make/libexec/gnubin' >> $GITHUB_PATH + if: runner.os == 'macOS' +diff --git a/.jcheck/conf b/.jcheck/conf +index 5636278120..d13b1bf5e8 100644 +--- a/.jcheck/conf ++++ b/.jcheck/conf +@@ -1,5 +1,5 @@ + [general] +-project=jdk-updates ++project=riscv-port + jbs=JDK + version=11.0.25 + +diff --git a/SECURITY.md b/SECURITY.md +new file mode 100644 +index 0000000000..f4c5e7e67c +--- /dev/null ++++ b/SECURITY.md +@@ -0,0 +1,3 @@ ++# JDK Vulnerabilities ++ ++Please follow the process outlined in the [OpenJDK Vulnerability Policy](https://openjdk.org/groups/vulnerability/report) to disclose vulnerabilities in the JDK. +diff --git a/make/autoconf/build-aux/config.sub b/make/autoconf/build-aux/config.sub +index 3c280ac7c0..6c66c221e0 100644 +--- a/make/autoconf/build-aux/config.sub ++++ b/make/autoconf/build-aux/config.sub @@ -1,6 +1,6 @@ #!/bin/sh # --# Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. -+# Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. - # Copyright (c) 2021, Azul Systems, Inc. All rights reserved. +-# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. ++# Copyright (c) 2014, 2022, 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 +@@ -40,6 +40,13 @@ if echo $* | grep pc-msys >/dev/null ; then + exit + fi + ++# Canonicalize for riscv which autoconf-config.sub doesn't handle ++if echo $* | grep '^riscv\(32\|64\)-linux' >/dev/null ; then ++ result=`echo $@ | sed 's/linux/unknown-linux/'` ++ echo $result ++ exit ++fi ++ + # First, filter out everything that doesn't begin with "aarch64-" + if ! echo $* | grep '^aarch64-' >/dev/null ; then + . $DIR/autoconf-config.sub "$@" diff --git a/make/autoconf/hotspot.m4 b/make/autoconf/hotspot.m4 -index 9bb34363e5c..f84e8f84c60 100644 +index 9bb34363e5..f84e8f84c6 100644 --- a/make/autoconf/hotspot.m4 +++ b/make/autoconf/hotspot.m4 @@ -370,7 +370,8 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_FEATURES], @@ -353,32 +211,8 @@ index 9bb34363e5c..f84e8f84c60 100644 AC_MSG_RESULT([yes]) else DISABLED_JVM_FEATURES="$DISABLED_JVM_FEATURES shenandoahgc" -diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 -index 16e906bdc6a..5c49fd9285d 100644 ---- a/make/autoconf/libraries.m4 -+++ b/make/autoconf/libraries.m4 -@@ -1,5 +1,5 @@ - # --# Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. -+# Copyright (c) 2011, 2022, 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 -@@ -130,6 +130,12 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], - BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lthread" - fi - -+ # Because RISC-V only has word-sized atomics, it requries libatomic where -+ # other common architectures do not. So link libatomic by default. -+ if test "x$OPENJDK_TARGET_OS" = xlinux && test "x$OPENJDK_TARGET_CPU" = xriscv64; then -+ BASIC_JVM_LIBS="$BASIC_JVM_LIBS -latomic" -+ fi -+ - # perfstat lib - if test "x$OPENJDK_TARGET_OS" = xaix; then - BASIC_JVM_LIBS="$BASIC_JVM_LIBS -lperfstat" diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4 -index 26a58eb2ee8..67972d89248 100644 +index 5d1d9efa39..565ca18e20 100644 --- a/make/autoconf/platform.m4 +++ b/make/autoconf/platform.m4 @@ -1,5 +1,5 @@ @@ -397,17 +231,21 @@ index 26a58eb2ee8..67972d89248 100644 # The cpu defines below are for zero, we don't support them directly. elif test "x$OPENJDK_$1_CPU" = xsparc; then -@@ -564,8 +566,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" = xriscv64; then -- HOTSPOT_$1_CPU_DEFINE=RISCV - elif test "x$OPENJDK_$1_CPU" = xloongarch64; then - HOTSPOT_$1_CPU_DEFINE=LOONGARCH64 - elif test "x$OPENJDK_$1_CPU" != x; then +diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers +index fe5e0d9850..c02b769bf2 100644 +--- a/make/autoconf/version-numbers ++++ b/make/autoconf/version-numbers +@@ -37,7 +37,7 @@ DEFAULT_VERSION_DATE=2024-10-15 + DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" + DEFAULT_VERSION_CLASSFILE_MINOR=0 + DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" +-DEFAULT_PROMOTED_VERSION_PRE= ++DEFAULT_PROMOTED_VERSION_PRE=ea + + LAUNCHER_NAME=openjdk + PRODUCT_NAME=OpenJDK diff --git a/make/hotspot/gensrc/GensrcAdlc.gmk b/make/hotspot/gensrc/GensrcAdlc.gmk -index c5a3ac5724b..67f4c6f0574 100644 +index c5a3ac5724..51137b99db 100644 --- a/make/hotspot/gensrc/GensrcAdlc.gmk +++ b/make/hotspot/gensrc/GensrcAdlc.gmk @@ -1,5 +1,5 @@ @@ -417,13 +255,12 @@ index c5a3ac5724b..67f4c6f0574 100644 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it -@@ -150,6 +150,13 @@ ifeq ($(call check-jvm-feature, compiler2), true) +@@ -150,6 +150,12 @@ ifeq ($(call check-jvm-feature, compiler2), true) $d/os_cpu/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_OS)_$(HOTSPOT_TARGET_CPU_ARCH).ad \ ))) + ifeq ($(HOTSPOT_TARGET_CPU_ARCH), riscv) + AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ -+ $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_v.ad \ + $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_b.ad \ + ))) + endif @@ -431,79 +268,97 @@ index c5a3ac5724b..67f4c6f0574 100644 ifeq ($(call check-jvm-feature, shenandoahgc), true) AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/gc/shenandoah/shenandoah_$(HOTSPOT_TARGET_CPU).ad \ -diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp -index fdd2c0ca3d7..63f193de86e 100644 ---- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp -+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +diff --git a/make/hotspot/lib/JvmFlags.gmk b/make/hotspot/lib/JvmFlags.gmk +index 3246c83155..1a91eb0079 100644 +--- a/make/hotspot/lib/JvmFlags.gmk ++++ b/make/hotspot/lib/JvmFlags.gmk +@@ -67,10 +67,12 @@ JVM_CFLAGS_TARGET_DEFINES += \ + # + + ifeq ($(DEBUG_LEVEL), release) ++ # release builds disable uses of assert macro from . ++ JVM_CFLAGS_DEBUGLEVEL := -DNDEBUG + # For hotspot, release builds differ internally between "optimized" and "product" + # in that "optimize" does not define PRODUCT. + ifneq ($(HOTSPOT_DEBUG_LEVEL), optimized) +- JVM_CFLAGS_DEBUGLEVEL := -DPRODUCT ++ JVM_CFLAGS_DEBUGLEVEL += -DPRODUCT + endif + else ifeq ($(DEBUG_LEVEL), fastdebug) + JVM_CFLAGS_DEBUGLEVEL := -DASSERT +diff --git a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java +index f02537c305..ef94e3879c 100644 +--- a/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java ++++ b/make/jdk/src/classes/build/tools/tzdb/TzdbZoneRulesProvider.java @@ -1,5 +1,5 @@ /* -- * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * -@@ -1593,7 +1593,9 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { - } - - --void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { -+void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, -+ LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { -+ assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on aarch64"); - - Assembler::Condition acond, ncond; - switch (condition) { -diff --git a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp -index f0a7229aa18..cb095052534 100644 ---- a/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp -+++ b/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. +- * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -1824,7 +1824,10 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { - } +@@ -363,33 +363,35 @@ class TzdbZoneRulesProvider { + } - --void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { -+void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, -+ LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { -+ assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on arm"); + Month parseMonth(String mon) { +- switch (mon) { +- case "Jan": return Month.JANUARY; +- case "Feb": return Month.FEBRUARY; +- case "Mar": return Month.MARCH; +- case "Apr": return Month.APRIL; +- case "May": return Month.MAY; +- case "Jun": return Month.JUNE; +- case "Jul": return Month.JULY; +- case "Aug": return Month.AUGUST; +- case "Sep": return Month.SEPTEMBER; +- case "Oct": return Month.OCTOBER; +- case "Nov": return Month.NOVEMBER; +- case "Dec": return Month.DECEMBER; +- } ++ int len = mon.length(); + - AsmCondition acond = al; - AsmCondition ncond = nv; - if (opr1 != opr2) { -diff --git a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp -index 847f7d61d2f..d74db914331 100644 ---- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp -+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp -@@ -1,6 +1,6 @@ - /* -- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2012, 2019, SAP SE. All rights reserved. -+ * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2012, 2021 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -1553,8 +1553,10 @@ inline void load_to_reg(LIR_Assembler *lasm, LIR_Opr src, LIR_Opr dst) { - } - } ++ if (mon.regionMatches(true, 0, "January", 0, len)) return Month.JANUARY; ++ if (mon.regionMatches(true, 0, "February", 0, len)) return Month.FEBRUARY; ++ if (mon.regionMatches(true, 0, "March", 0, len)) return Month.MARCH; ++ if (mon.regionMatches(true, 0, "April", 0, len)) return Month.APRIL; ++ if (mon.regionMatches(true, 0, "May", 0, len)) return Month.MAY; ++ if (mon.regionMatches(true, 0, "June", 0, len)) return Month.JUNE; ++ if (mon.regionMatches(true, 0, "July", 0, len)) return Month.JULY; ++ if (mon.regionMatches(true, 0, "August", 0, len)) return Month.AUGUST; ++ if (mon.regionMatches(true, 0, "September", 0, len)) return Month.SEPTEMBER; ++ if (mon.regionMatches(true, 0, "October", 0, len)) return Month.OCTOBER; ++ if (mon.regionMatches(true, 0, "November", 0, len)) return Month.NOVEMBER; ++ if (mon.regionMatches(true, 0, "December", 0, len)) return Month.DECEMBER; ++ + throw new IllegalArgumentException("Unknown month: " + mon); + } -+void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, -+ LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { -+ assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on ppc"); + DayOfWeek parseDayOfWeek(String dow) { +- switch (dow) { +- case "Mon": return DayOfWeek.MONDAY; +- case "Tue": return DayOfWeek.TUESDAY; +- case "Wed": return DayOfWeek.WEDNESDAY; +- case "Thu": return DayOfWeek.THURSDAY; +- case "Fri": return DayOfWeek.FRIDAY; +- case "Sat": return DayOfWeek.SATURDAY; +- case "Sun": return DayOfWeek.SUNDAY; +- } ++ int len = dow.length(); ++ ++ if (dow.regionMatches(true, 0, "Monday", 0, len)) return DayOfWeek.MONDAY; ++ if (dow.regionMatches(true, 0, "Tuesday", 0, len)) return DayOfWeek.TUESDAY; ++ if (dow.regionMatches(true, 0, "Wednesday", 0, len)) return DayOfWeek.WEDNESDAY; ++ if (dow.regionMatches(true, 0, "Thursday", 0, len)) return DayOfWeek.THURSDAY; ++ if (dow.regionMatches(true, 0, "Friday", 0, len)) return DayOfWeek.FRIDAY; ++ if (dow.regionMatches(true, 0, "Saturday", 0, len)) return DayOfWeek.SATURDAY; ++ if (dow.regionMatches(true, 0, "Sunday", 0, len)) return DayOfWeek.SUNDAY; ++ + throw new IllegalArgumentException("Unknown day-of-week: " + dow); + } --void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { - if (opr1->is_equal(opr2) || opr1->is_same_register(opr2)) { - load_to_reg(this, opr1, result); // Condition doesn't matter. - return; diff --git a/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp new file mode 100644 -index 00000000000..31c63abe71d +index 0000000000..31c63abe71 --- /dev/null +++ b/src/hotspot/cpu/riscv/abstractInterpreter_riscv.cpp @@ -0,0 +1,177 @@ @@ -686,10 +541,10 @@ index 00000000000..31c63abe71d +} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp new file mode 100644 -index 00000000000..f15ef5304c5 +index 0000000000..67c6f1eccb --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp -@@ -0,0 +1,372 @@ +@@ -0,0 +1,337 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -742,7 +597,7 @@ index 00000000000..f15ef5304c5 + } +} + -+void Assembler::addw(Register Rd, Register Rn, int64_t increment, Register temp) { ++void Assembler::addw(Register Rd, Register Rn, int32_t increment, Register temp) { + if (is_imm_in_range(increment, 12, 0)) { + addiw(Rd, Rn, increment); + } else { @@ -762,7 +617,7 @@ index 00000000000..f15ef5304c5 + } +} + -+void Assembler::subw(Register Rd, Register Rn, int64_t decrement, Register temp) { ++void Assembler::subw(Register Rd, Register Rn, int32_t decrement, Register temp) { + if (is_imm_in_range(-decrement, 12, 0)) { + addiw(Rd, Rn, -decrement); + } else { @@ -808,33 +663,6 @@ index 00000000000..f15ef5304c5 + } +} + -+void Assembler::li64(Register Rd, int64_t imm) { -+ // Load upper 32 bits. upper = imm[63:32], but if imm[31] == 1 or -+ // (imm[31:28] == 0x7ff && imm[19] == 1), upper = imm[63:32] + 1. -+ int64_t lower = imm & 0xffffffff; -+ lower -= ((lower << 44) >> 44); -+ int64_t tmp_imm = ((uint64_t)(imm & 0xffffffff00000000)) + (uint64_t)lower; -+ int32_t upper = (tmp_imm - (int32_t)lower) >> 32; -+ -+ // Load upper 32 bits -+ int64_t up = upper, lo = upper; -+ lo = (lo << 52) >> 52; -+ up -= lo; -+ up = (int32_t)up; -+ lui(Rd, up); -+ addi(Rd, Rd, lo); -+ -+ // Load the rest 32 bits. -+ slli(Rd, Rd, 12); -+ addi(Rd, Rd, (int32_t)lower >> 20); -+ slli(Rd, Rd, 12); -+ lower = ((int32_t)imm << 12) >> 20; -+ addi(Rd, Rd, lower); -+ slli(Rd, Rd, 8); -+ lower = imm & 0xff; -+ addi(Rd, Rd, lower); -+} -+ +void Assembler::li32(Register Rd, int32_t imm) { + // int32_t is in range 0x8000 0000 ~ 0x7fff ffff, and imm[31] is the sign bit + int64_t upper = imm, lower = imm; @@ -843,7 +671,6 @@ index 00000000000..f15ef5304c5 + upper = (int32_t)upper; + // lui Rd, imm[31:12] + imm[11] + lui(Rd, upper); -+ // use addiw to distinguish li32 to li64 + addiw(Rd, Rd, lower); +} + @@ -907,7 +734,7 @@ index 00000000000..f15ef5304c5 + void Assembler::NAME(const Address &adr, Register temp) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ -+ code_section()->relocate(pc(), adr.rspec()); \ ++ relocate(adr.rspec()); \ + NAME(adr.target(), temp); \ + break; \ + } \ @@ -965,7 +792,7 @@ index 00000000000..f15ef5304c5 +} + +void Assembler::movptr_with_offset(Register Rd, address addr, int32_t &offset) { -+ uintptr_t imm64 = (uintptr_t)addr; ++ int64_t imm64 = (int64_t)addr; +#ifndef PRODUCT + { + char buffer[64]; @@ -973,10 +800,10 @@ index 00000000000..f15ef5304c5 + block_comment(buffer); + } +#endif -+ assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (uintptr_t)-1), -+ "48-bit overflow in address constant"); -+ // Load upper 32 bits -+ int32_t imm = imm64 >> 16; ++ assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (int64_t)-1), ++ "bit 47 overflows in address constant"); ++ // Load upper 31 bits ++ int64_t imm = imm64 >> 17; + int64_t upper = imm, lower = imm; + lower = (lower << 52) >> 52; + upper -= lower; @@ -984,13 +811,13 @@ index 00000000000..f15ef5304c5 + lui(Rd, upper); + addi(Rd, Rd, lower); + -+ // Load the rest 16 bits. ++ // Load the rest 17 bits. + slli(Rd, Rd, 11); -+ addi(Rd, Rd, (imm64 >> 5) & 0x7ff); -+ slli(Rd, Rd, 5); ++ addi(Rd, Rd, (imm64 >> 6) & 0x7ff); ++ slli(Rd, Rd, 6); + + // This offset will be used by following jalr/ld. -+ offset = imm64 & 0x1f; ++ offset = imm64 & 0x3f; +} + +void Assembler::movptr(Register Rd, uintptr_t imm64) { @@ -1003,13 +830,6 @@ index 00000000000..f15ef5304c5 + addi(Rd, Rd, offset); +} + -+void Assembler::ifence() { -+ fence_i(); -+ if (UseConservativeFence) { -+ fence(ir, ir); -+ } -+} -+ +#define INSN(NAME, NEG_INSN) \ + void Assembler::NAME(Register Rs, Register Rt, const address &dest) { \ + NEG_INSN(Rt, Rs, dest); \ @@ -1064,10 +884,10 @@ index 00000000000..f15ef5304c5 +} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp new file mode 100644 -index 00000000000..4923962a496 +index 0000000000..9f6c477afa --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -0,0 +1,3047 @@ +@@ -0,0 +1,3056 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -1253,13 +1073,22 @@ index 00000000000..4923962a496 + : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } + Address(Register r) + : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } -+ -+ template::value)> -+ Address(Register r, T o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) {} -+ ++ Address(Register r, int o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++ Address(Register r, long o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++ Address(Register r, long long o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++ Address(Register r, unsigned int o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++ Address(Register r, unsigned long o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++ Address(Register r, unsigned long long o) ++ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } ++#ifdef ASSERT + Address(Register r, ByteSize disp) -+ : Address(r, in_bytes(disp)) {} ++ : _base(r), _index(noreg), _offset(in_bytes(disp)), _mode(base_plus_offset), _target(0) { } ++#endif + Address(address target, RelocationHolder const& rspec) + : _base(noreg), + _index(noreg), @@ -1338,14 +1167,6 @@ index 00000000000..4923962a496 + + enum { instruction_size = 4 }; + -+ //---< calculate length of instruction >--- -+ // We just use the values set above. -+ // instruction must start at passed address -+ static unsigned int instr_len(unsigned char *instr) { return instruction_size; } -+ -+ //---< longest instructions >--- -+ static unsigned int instr_maxlen() { return instruction_size; } -+ + enum RoundingMode { + rne = 0b000, // round to Nearest, ties to Even + rtz = 0b001, // round towards Zero @@ -1383,11 +1204,9 @@ index 00000000000..4923962a496 + + void _li(Register Rd, int64_t imm); // optimized load immediate + void li32(Register Rd, int32_t imm); -+ void li64(Register Rd, int64_t imm); + void movptr(Register Rd, address addr); + void movptr_with_offset(Register Rd, address addr, int32_t &offset); + void movptr(Register Rd, uintptr_t imm64); -+ void ifence(); + void j(const address &dest, Register temp = t0); + void j(const Address &adr, Register temp = t0); + void j(Label &l, Register temp = t0); @@ -1508,10 +1327,9 @@ index 00000000000..4923962a496 + +#define INSN_ENTRY_RELOC(result_type, header) \ + result_type header { \ -+ InstructionMark im(this); \ + guarantee(rtype == relocInfo::internal_word_type, \ + "only internal_word_type relocs make sense here"); \ -+ code_section()->relocate(inst_mark(), InternalAddress(dest).rspec()); ++ relocate(InternalAddress(dest).rspec()); + + // Load/store register (all modes) +#define INSN(NAME, op, funct3) \ @@ -1556,7 +1374,7 @@ index 00000000000..4923962a496 + void NAME(Register Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ -+ code_section()->relocate(pc(), adr.rspec()); \ ++ relocate(adr.rspec()); \ + NAME(Rd, adr.target()); \ + break; \ + } \ @@ -1630,7 +1448,7 @@ index 00000000000..4923962a496 + void NAME(FloatRegister Rd, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ -+ code_section()->relocate(pc(), adr.rspec()); \ ++ relocate(adr.rspec()); \ + NAME(Rd, adr.target(), temp); \ + break; \ + } \ @@ -1773,7 +1591,7 @@ index 00000000000..4923962a496 + switch (adr.getMode()) { \ + case Address::literal: { \ + assert_different_registers(Rs, temp); \ -+ code_section()->relocate(pc(), adr.rspec()); \ ++ relocate(adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ @@ -1816,7 +1634,7 @@ index 00000000000..4923962a496 + void NAME(FloatRegister Rs, const Address &adr, Register temp = t0) { \ + switch (adr.getMode()) { \ + case Address::literal: { \ -+ code_section()->relocate(pc(), adr.rspec()); \ ++ relocate(adr.rspec()); \ + NAME(Rs, adr.target(), temp); \ + break; \ + } \ @@ -1966,7 +1784,6 @@ index 00000000000..4923962a496 + emit(insn); \ + } + -+ INSN(fence_i, 0b0001111, 0b001, 0b000000000000); + INSN(ecall, 0b1110011, 0b000, 0b000000000000); + INSN(_ebreak, 0b1110011, 0b000, 0b000000000001); + @@ -3014,6 +2831,7 @@ index 00000000000..4923962a496 + +// ==================================== +// RISC-V Bit-Manipulation Extension ++// Currently only support Zba, Zbb and Zbs bitmanip extensions. +// ==================================== +#define INSN(NAME, op, funct3, funct7) \ + void NAME(Register Rd, Register Rs1, Register Rs2) { \ @@ -3088,6 +2906,7 @@ index 00000000000..4923962a496 + + INSN(rori, 0b0010011, 0b101, 0b011000); + INSN(slli_uw, 0b0011011, 0b001, 0b000010); ++ INSN(bexti, 0b0010011, 0b101, 0b010010); + +#undef INSN + @@ -4084,11 +3903,12 @@ index 00000000000..4923962a496 + void wrap_label(Register r, Label &L, Register t, load_insn_by_temp insn); + void wrap_label(Register r, Label &L, jal_jalr_insn insn); + -+ // calculate pseudoinstruction ++ // Computational pseudo instructions + void add(Register Rd, Register Rn, int64_t increment, Register temp = t0); -+ void addw(Register Rd, Register Rn, int64_t increment, Register temp = t0); ++ void addw(Register Rd, Register Rn, int32_t increment, Register temp = t0); ++ + void sub(Register Rd, Register Rn, int64_t decrement, Register temp = t0); -+ void subw(Register Rd, Register Rn, int64_t decrement, Register temp = t0); ++ void subw(Register Rd, Register Rn, int32_t decrement, Register temp = t0); + + // RVB pseudo instructions + // zero extend word @@ -4097,6 +3917,13 @@ index 00000000000..4923962a496 + Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) { + } + ++ virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, ++ Register tmp, ++ int offset) { ++ ShouldNotCallThis(); ++ return RegisterOrConstant(); ++ } ++ + // Stack overflow checking + virtual void bang_stack_with_offset(int offset) { Unimplemented(); } + @@ -4114,10 +3941,12 @@ index 00000000000..4923962a496 + virtual ~Assembler() {} +}; + ++class BiasedLockingCounters; ++ +#endif // CPU_RISCV_ASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp new file mode 100644 -index 00000000000..7ffe8803985 +index 0000000000..7ffe880398 --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.inline.hpp @@ -0,0 +1,47 @@ @@ -4170,7 +3999,7 @@ index 00000000000..7ffe8803985 +#endif // CPU_RISCV_ASSEMBLER_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/bytes_riscv.hpp b/src/hotspot/cpu/riscv/bytes_riscv.hpp new file mode 100644 -index 00000000000..23d982f9abd +index 0000000000..485a5f9355 --- /dev/null +++ b/src/hotspot/cpu/riscv/bytes_riscv.hpp @@ -0,0 +1,167 @@ @@ -4203,8 +4032,6 @@ index 00000000000..23d982f9abd +#ifndef CPU_RISCV_BYTES_RISCV_HPP +#define CPU_RISCV_BYTES_RISCV_HPP + -+#include "memory/allStatic.hpp" -+ +class Bytes: AllStatic { + public: + // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering @@ -4251,6 +4078,7 @@ index 00000000000..23d982f9abd + ((u8)(((u4*)p)[0])); + + case 2: ++ case 6: + return ((u8)(((u2*)p)[3]) << 48) | + ((u8)(((u2*)p)[2]) << 32) | + ((u8)(((u2*)p)[1]) << 16) | @@ -4309,6 +4137,7 @@ index 00000000000..23d982f9abd + break; + + case 2: ++ case 6: + ((u2*)p)[3] = x >> 48; + ((u2*)p)[2] = x >> 32; + ((u2*)p)[1] = x >> 16; @@ -4343,10 +4172,10 @@ index 00000000000..23d982f9abd +#endif // CPU_RISCV_BYTES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp new file mode 100644 -index 00000000000..dcd0472c540 +index 0000000000..9729e16c96 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -@@ -0,0 +1,353 @@ +@@ -0,0 +1,339 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -4388,20 +4217,6 @@ index 00000000000..dcd0472c540 + +#define __ ce->masm()-> + -+void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { -+ __ bind(_entry); -+ InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset()); -+ __ code_section()->relocate(__ pc(), safepoint_pc.rspec()); -+ __ la(t0, safepoint_pc.target()); -+ __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); -+ -+ assert(SharedRuntime::polling_page_return_handler_blob() != NULL, -+ "polling page return stub not created yet"); -+ address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); -+ -+ __ far_jump(RuntimeAddress(stub)); -+} -+ +void CounterOverflowStub::emit_code(LIR_Assembler* ce) { + __ bind(_entry); + Metadata *m = _method->as_constant_ptr()->as_metadata(); @@ -4421,7 +4236,7 @@ index 00000000000..dcd0472c540 +} + +RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index) -+ : _index(index), _array(), _throw_index_out_of_bounds_exception(true) { ++ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) { + assert(info != NULL, "must have info"); + _info = new CodeEmitInfo(info); +} @@ -4446,7 +4261,7 @@ index 00000000000..dcd0472c540 + if (_throw_index_out_of_bounds_exception) { + stub_id = Runtime1::throw_index_exception_id; + } else { -+ assert(_array != LIR_Opr::nullOpr(), "sanity"); ++ assert(_array != NULL, "sanity"); + __ mv(t1, _array->as_pointer_register()); + stub_id = Runtime1::throw_range_check_failed_id; + } @@ -4653,7 +4468,7 @@ index 00000000000..dcd0472c540 + const int args_num = 5; + VMRegPair args[args_num]; + BasicType signature[args_num] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT }; -+ SharedRuntime::java_calling_convention(signature, args, args_num); ++ SharedRuntime::java_calling_convention(signature, args, args_num, true); + + // push parameters + Register r[args_num]; @@ -4692,7 +4507,7 @@ index 00000000000..dcd0472c540 +#ifndef PRODUCT + if (PrintC1Statistics) { + __ la(t1, ExternalAddress((address)&Runtime1::_arraycopy_slowcase_cnt)); -+ __ add_memory_int32(Address(t1), 1); ++ __ incrementw(Address(t1)); + } +#endif + @@ -4702,7 +4517,7 @@ index 00000000000..dcd0472c540 +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp new file mode 100644 -index 00000000000..4417ad63091 +index 0000000000..4417ad6309 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_Defs_riscv.hpp @@ -0,0 +1,84 @@ @@ -4792,7 +4607,7 @@ index 00000000000..4417ad63091 +#endif // CPU_RISCV_C1_DEFS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp new file mode 100644 -index 00000000000..e3a2606c532 +index 0000000000..e3a2606c53 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.cpp @@ -0,0 +1,30 @@ @@ -4828,7 +4643,7 @@ index 00000000000..e3a2606c532 +// No FPU stack on RISCV diff --git a/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp new file mode 100644 -index 00000000000..7bc3d311501 +index 0000000000..7bc3d31150 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FpuStackSim_riscv.hpp @@ -0,0 +1,32 @@ @@ -4866,7 +4681,7 @@ index 00000000000..7bc3d311501 +#endif // CPU_RISCV_C1_FPUSTACKSIM_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp new file mode 100644 -index 00000000000..172031941b2 +index 0000000000..682ebe8262 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp @@ -0,0 +1,388 @@ @@ -5028,8 +4843,8 @@ index 00000000000..172031941b2 +LIR_Opr FrameMap::fpu10_float_opr; +LIR_Opr FrameMap::fpu10_double_opr; + -+LIR_Opr FrameMap::_caller_save_cpu_regs[] = {}; -+LIR_Opr FrameMap::_caller_save_fpu_regs[] = {}; ++LIR_Opr FrameMap::_caller_save_cpu_regs[] = { 0, }; ++LIR_Opr FrameMap::_caller_save_fpu_regs[] = { 0, }; + +//-------------------------------------------------------- +// FrameMap @@ -5186,7 +5001,7 @@ index 00000000000..172031941b2 + + VMRegPair regs; + BasicType sig_bt = T_OBJECT; -+ SharedRuntime::java_calling_convention(&sig_bt, ®s, 1); ++ SharedRuntime::java_calling_convention(&sig_bt, ®s, 1, true); + receiver_opr = as_oop_opr(regs.first()->as_Register()); + + for (i = 0; i < nof_caller_save_fpu_regs; i++) { @@ -5260,7 +5075,7 @@ index 00000000000..172031941b2 +} diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp new file mode 100644 -index 00000000000..01281f5c9e1 +index 0000000000..01281f5c9e --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.hpp @@ -0,0 +1,148 @@ @@ -5414,10 +5229,10 @@ index 00000000000..01281f5c9e1 +#endif // CPU_RISCV_C1_FRAMEMAP_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp new file mode 100644 -index 00000000000..4c1c13dc290 +index 0000000000..2a99d49c94 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -@@ -0,0 +1,281 @@ +@@ -0,0 +1,285 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -5610,7 +5425,7 @@ index 00000000000..4c1c13dc290 + code == lir_add ? __ add(dreg, lreg_lo, c) : __ sub(dreg, lreg_lo, c); + break; + case lir_div: -+ assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); ++ assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); + if (c == 1) { + // move lreg_lo to dreg if divisor is 1 + __ mv(dreg, lreg_lo); @@ -5628,7 +5443,7 @@ index 00000000000..4c1c13dc290 + } + break; + case lir_rem: -+ assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); ++ assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); + if (c == 1) { + // move 0 to dreg if divisor is 1 + __ mv(dreg, zr); @@ -5658,7 +5473,9 @@ index 00000000000..4c1c13dc290 + switch (code) { + case lir_add: __ fadd_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + case lir_sub: __ fsub_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; ++ case lir_mul_strictfp: // fall through + case lir_mul: __ fmul_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; ++ case lir_div_strictfp: // fall through + case lir_div: __ fdiv_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; + default: + ShouldNotReachHere(); @@ -5671,7 +5488,9 @@ index 00000000000..4c1c13dc290 + switch (code) { + case lir_add: __ fadd_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + case lir_sub: __ fsub_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; ++ case lir_mul_strictfp: // fall through + case lir_mul: __ fmul_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; ++ case lir_div_strictfp: // fall through + case lir_div: __ fdiv_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; + default: + ShouldNotReachHere(); @@ -5701,7 +5520,7 @@ index 00000000000..4c1c13dc290 +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp new file mode 100644 -index 00000000000..ab0a9963fc1 +index 0000000000..ab0a9963fc --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.hpp @@ -0,0 +1,37 @@ @@ -5744,7 +5563,7 @@ index 00000000000..ab0a9963fc1 +#endif // CPU_RISCV_C1_LIRASSEMBLER_ARITH_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp new file mode 100644 -index 00000000000..b7f53e395f3 +index 0000000000..e6b95d3b7f --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -0,0 +1,388 @@ @@ -5807,7 +5626,7 @@ index 00000000000..b7f53e395f3 + __ mv(c_rarg4, j_rarg4); +#ifndef PRODUCT + if (PrintC1Statistics) { -+ __ add_memory_int32(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt), 1); ++ __ incrementw(ExternalAddress((address)&Runtime1::_generic_arraycopystub_cnt)); + } +#endif + __ far_call(RuntimeAddress(copyfunc_addr)); @@ -5845,14 +5664,14 @@ index 00000000000..b7f53e395f3 + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) { + __ load_klass(tmp, dst); + __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset()))); -+ __ li(t1, Klass::_lh_neutral_value); ++ __ mv(t1, Klass::_lh_neutral_value); + __ bge(t0, t1, *stub->entry(), /* is_far */ true); + } + + if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) { + __ load_klass(tmp, src); + __ lw(t0, Address(tmp, in_bytes(Klass::layout_helper_offset()))); -+ __ li(t1, Klass::_lh_neutral_value); ++ __ mv(t1, Klass::_lh_neutral_value); + __ bge(t0, t1, *stub->entry(), /* is_far */ true); + } + } @@ -5914,7 +5733,7 @@ index 00000000000..b7f53e395f3 + if (PrintC1Statistics) { + Label failed; + __ bnez(x10, failed); -+ __ add_memory_int32(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_cnt), 1); ++ __ incrementw(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_cnt)); + __ bind(failed); + } +#endif @@ -5923,7 +5742,7 @@ index 00000000000..b7f53e395f3 + +#ifndef PRODUCT + if (PrintC1Statistics) { -+ __ add_memory_int32(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_attempt_cnt), 1); ++ __ incrementw(ExternalAddress((address)&Runtime1::_arraycopy_checkcast_attempt_cnt)); + } +#endif + assert_different_registers(dst, dst_pos, length, src_pos, src, x10, t0); @@ -6074,7 +5893,7 @@ index 00000000000..b7f53e395f3 + +#ifndef PRODUCT + if (PrintC1Statistics) { -+ __ add_memory_int32(ExternalAddress(Runtime1::arraycopy_count_address(basic_type)), 1); ++ __ incrementw(ExternalAddress(Runtime1::arraycopy_count_address(basic_type))); + } +#endif + arraycopy_prepare_params(src, src_pos, length, dst, dst_pos, basic_type); @@ -6138,7 +5957,7 @@ index 00000000000..b7f53e395f3 +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp new file mode 100644 -index 00000000000..06a0f248ca6 +index 0000000000..06a0f248ca --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp @@ -0,0 +1,52 @@ @@ -6196,10 +6015,10 @@ index 00000000000..06a0f248ca6 +#endif // CPU_RISCV_C1_LIRASSEMBLER_ARRAYCOPY_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp new file mode 100644 -index 00000000000..742c2126e60 +index 0000000000..fb6a60fb49 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -0,0 +1,2267 @@ +@@ -0,0 +1,2258 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -6243,7 +6062,6 @@ index 00000000000..742c2126e60 +#include "oops/objArrayKlass.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/sharedRuntime.hpp" -+#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + +#ifndef PRODUCT @@ -6293,18 +6111,6 @@ index 00000000000..742c2126e60 + +bool LIR_Assembler::is_small_constant(LIR_Opr opr) { Unimplemented(); return false; } + -+void LIR_Assembler::clinit_barrier(ciMethod* method) { -+ assert(VM_Version::supports_fast_class_init_checks(), "sanity"); -+ assert(!method->holder()->is_not_initialized(), "initialization should have been started"); -+ -+ Label L_skip_barrier; -+ -+ __ mov_metadata(t1, method->holder()->constant_encoding()); -+ __ clinit_barrier(t1, t0, &L_skip_barrier /* L_fast_path */); -+ __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -+ __ bind(L_skip_barrier); -+} -+ +LIR_Opr LIR_Assembler::receiverOpr() { + return FrameMap::receiver_opr; +} @@ -6569,11 +6375,7 @@ index 00000000000..742c2126e60 + if (method()->is_synchronized()) { + monitor_address(0, FrameMap::r10_opr); + stub = new MonitorExitStub(FrameMap::r10_opr, true, 0); -+ if (UseHeavyMonitors) { -+ __ j(*stub->entry()); -+ } else { -+ __ unlock_object(x15, x14, x10, *stub->entry()); -+ } ++ __ unlock_object(x15, x14, x10, *stub->entry()); + __ bind(*stub->continuation()); + } + @@ -6626,7 +6428,7 @@ index 00000000000..742c2126e60 + return offset; +} + -+void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { ++void LIR_Assembler::return_op(LIR_Opr result) { + assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == x10, "word returns are in x10"); + + // Pop the stack before the safepoint code @@ -6636,18 +6438,20 @@ index 00000000000..742c2126e60 + __ reserved_stack_check(); + } + -+ code_stub->set_safepoint_offset(__ offset()); -+ __ relocate(relocInfo::poll_return_type); -+ __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); ++ address polling_page(os::get_polling_page()); ++ __ read_polling_page(t0, polling_page, relocInfo::poll_return_type); + __ ret(); +} + +int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { ++ address polling_page(os::get_polling_page()); + guarantee(info != NULL, "Shouldn't be NULL"); -+ __ get_polling_page(t0, relocInfo::poll_type); ++ assert(os::is_poll_address(polling_page), "should be"); ++ int32_t offset = 0; ++ __ get_polling_page(t0, polling_page, offset, relocInfo::poll_type); + add_debug_info_for_branch(info); // This isn't just debug info: + // it's the oop map -+ __ read_polling_page(t0, 0, relocInfo::poll_type); ++ __ read_polling_page(t0, offset, relocInfo::poll_type); + return __ offset(); +} + @@ -6878,7 +6682,7 @@ index 00000000000..742c2126e60 + } +} + -+void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide) { ++void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) { + LIR_Address* to_addr = dest->as_address_ptr(); + // t0 was used as tmp reg in as_Address, so we use t1 as compressed_src + Register compressed_src = t1; @@ -7000,7 +6804,7 @@ index 00000000000..742c2126e60 + reg2stack(temp, dest, dest->type(), false); +} + -+void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide) { ++void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) { + assert(src->is_address(), "should not call otherwise"); + assert(dest->is_register(), "should not call otherwise"); + @@ -7045,7 +6849,14 @@ index 00000000000..742c2126e60 + __ ld(dest->as_register(), as_Address(from_addr)); + break; + case T_ADDRESS: -+ __ ld(dest->as_register(), as_Address(from_addr)); ++ // FIXME: OMG this is a horrible kludge. Any offset from an ++ // address that matches klass_offset_in_bytes() will be loaded ++ // as a word, not a long. ++ if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { ++ __ lwu(dest->as_register(), as_Address(from_addr)); ++ } else { ++ __ ld(dest->as_register(), as_Address(from_addr)); ++ } + break; + case T_INT: + __ lw(dest->as_register(), as_Address(from_addr)); @@ -7073,10 +6884,10 @@ index 00000000000..742c2126e60 + if (UseCompressedOops && !wide) { + __ decode_heap_oop(dest->as_register()); + } -+ -+ if (!UseZGC) { -+ // Load barrier has not yet been applied, so ZGC can't verify the oop here -+ __ verify_oop(dest->as_register()); ++ __ verify_oop(dest->as_register()); ++ } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { ++ if (UseCompressedClassPointers) { ++ __ decode_klass_not_null(dest->as_register()); + } + } +} @@ -7119,11 +6930,13 @@ index 00000000000..742c2126e60 + Label done; + move_op(opr2, result, type, lir_patch_none, NULL, + false, // pop_fpu_stack ++ false, // unaligned + false); // wide + __ j(done); + __ bind(label); + move_op(opr1, result, type, lir_patch_none, NULL, + false, // pop_fpu_stack ++ false, // unaligned + false); // wide + __ bind(done); +} @@ -7273,7 +7086,7 @@ index 00000000000..742c2126e60 + __ ld(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); + __ bne(recv, t1, next_test); + Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); -+ __ add_memory_int64(data_addr, DataLayout::counter_increment); ++ __ increment(data_addr, DataLayout::counter_increment); + __ j(*update_done); + __ bind(next_test); + } @@ -7285,7 +7098,7 @@ index 00000000000..742c2126e60 + __ ld(t1, recv_addr); + __ bnez(t1, next_test); + __ sd(recv, recv_addr); -+ __ li(t1, DataLayout::counter_increment); ++ __ mv(t1, DataLayout::counter_increment); + __ sd(t1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)))); + __ j(*update_done); + __ bind(next_test); @@ -7470,7 +7283,7 @@ index 00000000000..742c2126e60 + assert(op->addr()->is_address(), "what else?"); + LIR_Address* addr_ptr = op->addr()->as_address_ptr(); + assert(addr_ptr->disp() == 0, "need 0 disp"); -+ assert(addr_ptr->index() == LIR_Opr::illegalOpr(), "need 0 index"); ++ assert(addr_ptr->index() == LIR_OprDesc::illegalOpr(), "need 0 index"); + addr = as_reg(addr_ptr->base()); + } + Register newval = as_reg(op->new_value()); @@ -7565,7 +7378,7 @@ index 00000000000..742c2126e60 + // With RVC a call instruction may get 2-byte aligned. + // The address of the call instruction needs to be 4-byte aligned to + // ensure that it does not span a cache line so that it can be patched. -+ __ align(4); ++ __ align(NativeInstruction::instruction_size); +} + +void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { @@ -7586,9 +7399,14 @@ index 00000000000..742c2126e60 + add_call_info(code_offset(), op->info()); +} + ++/* Currently, vtable-dispatch is only enabled for sparc platforms */ ++void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { ++ ShouldNotReachHere(); ++} ++ +void LIR_Assembler::emit_static_call_stub() { + address call_pc = __ pc(); -+ assert((__ offset() % 4) == 0, "bad alignment"); ++ MacroAssembler::assert_alignment(call_pc); + address stub = __ start_a_stub(call_stub_size()); + if (stub == NULL) { + bailout("static call stub overflow"); @@ -7711,12 +7529,16 @@ index 00000000000..742c2126e60 + Register obj = op->obj_opr()->as_register(); // may not be an oop + Register hdr = op->hdr_opr()->as_register(); + Register lock = op->lock_opr()->as_register(); -+ if (UseHeavyMonitors) { ++ if (!UseFastLocking) { + __ j(*op->stub()->entry()); + } else if (op->code() == lir_lock) { ++ Register scratch = noreg; ++ if (UseBiasedLocking) { ++ scratch = op->scratch_opr()->as_register(); ++ } + assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); + // add debug info for NullPointerException only if one is possible -+ int null_check_offset = __ lock_object(hdr, obj, lock, *op->stub()->entry()); ++ int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry()); + if (op->info() != NULL) { + add_debug_info_for_null_check(null_check_offset, op->info()); + } @@ -7729,23 +7551,6 @@ index 00000000000..742c2126e60 + __ bind(*op->stub()->continuation()); +} + -+void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { -+ Register obj = op->obj()->as_pointer_register(); -+ Register result = op->result_opr()->as_pointer_register(); -+ -+ CodeEmitInfo* info = op->info(); -+ if (info != NULL) { -+ add_debug_info_for_null_check_here(info); -+ } -+ -+ if (UseCompressedClassPointers) { -+ __ lwu(result, Address(obj, oopDesc::klass_offset_in_bytes())); -+ __ decode_klass_not_null(result); -+ } else { -+ __ ld(result, Address(obj, oopDesc::klass_offset_in_bytes())); -+ } -+} -+ +void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { + ciMethod* method = op->profiled_method(); + int bci = op->profiled_bci(); @@ -7779,7 +7584,7 @@ index 00000000000..742c2126e60 + ciKlass* receiver = vc_data->receiver(i); + if (known_klass->equals(receiver)) { + Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); -+ __ add_memory_int64(data_addr, DataLayout::counter_increment); ++ __ increment(data_addr, DataLayout::counter_increment); + return; + } + } @@ -7795,7 +7600,7 @@ index 00000000000..742c2126e60 + __ mov_metadata(t1, known_klass->constant_encoding()); + __ sd(t1, recv_addr); + Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); -+ __ add_memory_int64(data_addr, DataLayout::counter_increment); ++ __ increment(data_addr, DataLayout::counter_increment); + return; + } + } @@ -7805,13 +7610,13 @@ index 00000000000..742c2126e60 + type_profile_helper(mdo, md, data, recv, &update_done); + // Receiver did not match any saved receiver and there is no empty row for it. + // Increment total counter to indicate polymorphic case. -+ __ add_memory_int64(counter_addr, DataLayout::counter_increment); ++ __ increment(counter_addr, DataLayout::counter_increment); + + __ bind(update_done); + } + } else { + // Static call -+ __ add_memory_int64(counter_addr, DataLayout::counter_increment); ++ __ increment(counter_addr, DataLayout::counter_increment); + } +} + @@ -7846,7 +7651,7 @@ index 00000000000..742c2126e60 + + if (TypeEntries::is_type_none(current_klass)) { + __ beqz(t1, none); -+ __ li(t0, (u1)TypeEntries::null_seen); ++ __ mv(t0, (u1)TypeEntries::null_seen); + __ beq(t0, t1, none); + // There is a chance that the checks above (re-reading profiling + // data from memory) fail if another thread has just set the @@ -7896,7 +7701,7 @@ index 00000000000..742c2126e60 + Label ok; + __ ld(t0, mdo_addr); + __ beqz(t0, ok); -+ __ li(t1, (u1)TypeEntries::null_seen); ++ __ mv(t1, (u1)TypeEntries::null_seen); + __ beq(t0, t1, ok); + // may have been set by another thread + __ membar(MacroAssembler::LoadLoad); @@ -8016,11 +7821,14 @@ index 00000000000..742c2126e60 + + +void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { -+ if (patch_code != lir_patch_none) { ++#if INCLUDE_SHENANDOAHGC ++ if (UseShenandoahGC && patch_code != lir_patch_none) { + deoptimize_trap(info); + return; + } ++#endif + ++ assert(patch_code == lir_patch_none, "Patch code not supported"); + LIR_Address* adr = addr->as_address_ptr(); + Register dst = dest->as_register_lo(); + @@ -8063,7 +7871,7 @@ index 00000000000..742c2126e60 + +void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { + if (dest->is_address() || src->is_address()) { -+ move_op(src, dest, type, lir_patch_none, info, /* pop_fpu_stack */ false, /* wide */ false); ++ move_op(src, dest, type, lir_patch_none, info, /* pop_fpu_stack */ false, /*unaligned*/ false, /* wide */ false); + } else { + ShouldNotReachHere(); + } @@ -8223,6 +8031,18 @@ index 00000000000..742c2126e60 + } +} + ++void LIR_Assembler::set_24bit_FPU() { Unimplemented(); } ++ ++void LIR_Assembler::reset_FPU() { Unimplemented(); } ++ ++void LIR_Assembler::fpop() { Unimplemented(); } ++ ++void LIR_Assembler::fxch(int i) { Unimplemented(); } ++ ++void LIR_Assembler::fld(int i) { Unimplemented(); } ++ ++void LIR_Assembler::ffree(int i) { Unimplemented(); } ++ +void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { + __ cmpxchg(addr, cmpval, newval, Assembler::int32, Assembler::aq /* acquire */, + Assembler::rl /* release */, t0, true /* result as bool */); @@ -8356,16 +8176,6 @@ index 00000000000..742c2126e60 + __ bind(done); +} + -+void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) { -+ _masm->code_section()->relocate(adr, relocInfo::poll_type); -+ int pc_offset = code_offset(); -+ flush_debug_info(pc_offset); -+ info->record_debug_info(compilation()->debug_info_recorder(), pc_offset); -+ if (info->exception_handlers() != NULL) { -+ compilation()->add_exception_handlers_for_pco(pc_offset, info->exception_handlers()); -+ } -+} -+ +void LIR_Assembler::type_profile(Register obj, ciMethodData* md, Register klass_RInfo, Register k_RInfo, + ciProfileData* data, Label* success, Label* failure, + Label& profile_cast_success, Label& profile_cast_failure) { @@ -8462,17 +8272,17 @@ index 00000000000..742c2126e60 + assert(offset_from_rsp_in_words >= 0, "invalid offset from rsp"); + int offset_from_rsp_in_bytes = offset_from_rsp_in_words * BytesPerWord; + assert(offset_from_rsp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); -+ __ li(t0, c); ++ __ mv(t0, c); + __ sd(t0, Address(sp, offset_from_rsp_in_bytes)); +} + +#undef __ diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp new file mode 100644 -index 00000000000..051328c3a8a +index 0000000000..2afd61a3db --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp -@@ -0,0 +1,132 @@ +@@ -0,0 +1,131 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -8533,8 +8343,6 @@ index 00000000000..051328c3a8a + ciMethodData *md, ciProfileData *data, + Register recv, Label* update_done); + -+ void add_debug_info_for_branch(address adr, CodeEmitInfo* info); -+ + void casw(Register addr, Register newval, Register cmpval); + void caswu(Register addr, Register newval, Register cmpval); + void casl(Register addr, Register newval, Register cmpval); @@ -8548,6 +8356,7 @@ index 00000000000..051328c3a8a + // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address) + _call_stub_size = 14 * NativeInstruction::instruction_size + + (NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size), ++ _call_aot_stub_size = 0, + // See emit_exception_handler for detail + // verify_not_null_oop + far_call + should_not_reach_here + invalidate_registers(DEBUG_ONLY) + _exception_handler_size = DEBUG_ONLY(584) NOT_DEBUG(548), // or smaller @@ -8607,10 +8416,10 @@ index 00000000000..051328c3a8a +#endif // CPU_RISCV_C1_LIRASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp new file mode 100644 -index 00000000000..e126f148cdf +index 0000000000..c41819fc2a --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -0,0 +1,1075 @@ +@@ -0,0 +1,1094 @@ +/* + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -8651,7 +8460,6 @@ index 00000000000..e126f148cdf +#include "ci/ciTypeArrayKlass.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" -+#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + +#ifdef ASSERT @@ -8819,6 +8627,7 @@ index 00000000000..e126f148cdf + break; + default: + ShouldNotReachHere(); ++ r = NULL; + } + return r; +} @@ -8890,6 +8699,11 @@ index 00000000000..e126f148cdf + + // "lock" stores the address of the monitor stack slot, so this is not an oop + LIR_Opr lock = new_register(T_INT); ++ // Need a scratch register for biased locking ++ LIR_Opr scratch = LIR_OprFact::illegalOpr; ++ if (UseBiasedLocking) { ++ scratch = new_register(T_INT); ++ } + + CodeEmitInfo* info_for_exception = NULL; + if (x->needs_null_check()) { @@ -8898,7 +8712,7 @@ index 00000000000..e126f148cdf + // this CodeEmitInfo must not have the xhandlers because here the + // object is already locked (xhandlers expect object to be unlocked) + CodeEmitInfo* info = state_for(x, x->state(), true); -+ monitor_enter(obj.result(), lock, syncTempOpr(), LIR_OprFact::illegalOpr, ++ monitor_enter(obj.result(), lock, syncTempOpr(), scratch, + x->monitor_no(), info_for_exception, info); +} + @@ -8968,7 +8782,12 @@ index 00000000000..e126f148cdf + right.load_item(); + + LIR_Opr reg = rlock(x); -+ arithmetic_op_fpu(x->op(), reg, left.result(), right.result()); ++ LIR_Opr tmp = LIR_OprFact::illegalOpr; ++ if (x->is_strictfp() && (x->op() == Bytecodes::_dmul || x->op() == Bytecodes::_ddiv)) { ++ tmp = new_register(T_DOUBLE); ++ } ++ ++ arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), x->is_strictfp()); + + set_result(x, round_item(reg)); +} @@ -8990,7 +8809,7 @@ index 00000000000..e126f148cdf + // no need to do div-by-zero check if the divisor is a non-zero constant + if (c != 0) { need_zero_check = false; } + // do not load right if the divisor is a power-of-2 constant -+ if (c > 0 && is_power_of_2(c)) { ++ if (c > 0 && is_power_of_2_long(c)) { + right.dont_load_item(); + } else { + right.load_item(); @@ -9001,7 +8820,7 @@ index 00000000000..e126f148cdf + if (need_zero_check) { + CodeEmitInfo* info = state_for(x); + __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0)); -+ __ branch(lir_cond_equal, new DivByZeroStub(info)); ++ __ branch(lir_cond_equal, T_LONG, new DivByZeroStub(info)); + } + + rlock_result(x); @@ -9075,7 +8894,7 @@ index 00000000000..e126f148cdf + if (need_zero_check) { + CodeEmitInfo* info = state_for(x); + __ cmp(lir_cond_equal, right_arg->result(), LIR_OprFact::longConst(0)); -+ __ branch(lir_cond_equal, new DivByZeroStub(info)); ++ __ branch(lir_cond_equal, T_INT, new DivByZeroStub(info)); + } + + LIR_Opr ill = LIR_OprFact::illegalOpr; @@ -9254,16 +9073,14 @@ index 00000000000..e126f148cdf + do_LibmIntrinsic(x); + break; + case vmIntrinsics::_dabs: // fall through -+ case vmIntrinsics::_dsqrt: // fall through -+ case vmIntrinsics::_dsqrt_strict: { ++ case vmIntrinsics::_dsqrt: { + assert(x->number_of_arguments() == 1, "wrong type"); + LIRItem value(x->argument_at(0), this); + value.load_item(); + LIR_Opr dst = rlock_result(x); + + switch (x->id()) { -+ case vmIntrinsics::_dsqrt: // fall through -+ case vmIntrinsics::_dsqrt_strict: { ++ case vmIntrinsics::_dsqrt: { + __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr); + break; + } @@ -9284,19 +9101,30 @@ index 00000000000..e126f148cdf +void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) { + LIRItem value(x->argument_at(0), this); + value.set_destroys_register(); ++ + LIR_Opr calc_result = rlock_result(x); + LIR_Opr result_reg = result_register_for(x->type()); ++ + CallingConvention* cc = NULL; -+ BasicTypeList signature(1); -+ signature.append(T_DOUBLE); -+ if (x->id() == vmIntrinsics::_dpow) { signature.append(T_DOUBLE); } -+ cc = frame_map()->c_calling_convention(&signature); -+ value.load_item_force(cc->at(0)); ++ + if (x->id() == vmIntrinsics::_dpow) { + LIRItem value1(x->argument_at(1), this); ++ + value1.set_destroys_register(); ++ ++ BasicTypeList signature(2); ++ signature.append(T_DOUBLE); ++ signature.append(T_DOUBLE); ++ cc = frame_map()->c_calling_convention(&signature); ++ value.load_item_force(cc->at(0)); + value1.load_item_force(cc->at(1)); ++ } else { ++ BasicTypeList signature(1); ++ signature.append(T_DOUBLE); ++ cc = frame_map()->c_calling_convention(&signature); ++ value.load_item_force(cc->at(0)); + } ++ + switch (x->id()) { + case vmIntrinsics::_dexp: + if (StubRoutines::dexp() != NULL) { __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args()); } @@ -9663,9 +9491,9 @@ index 00000000000..e126f148cdf + profile_branch(x, cond); + move_to_phi(x->state()); + if (x->x()->type()->is_float_kind()) { -+ __ branch(lir_cond(cond), x->tsux(), x->usux()); ++ __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux()); + } else { -+ __ branch(lir_cond(cond), x->tsux()); ++ __ branch(lir_cond(cond), right->type(), x->tsux()); + } + assert(x->default_sux() == x->fsux(), "wrong destination above"); + __ jump(x->default_sux()); @@ -9688,7 +9516,7 @@ index 00000000000..e126f148cdf +} diff --git a/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp new file mode 100644 -index 00000000000..5f1c394ab3d +index 0000000000..0317ed9003 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp @@ -0,0 +1,55 @@ @@ -9721,22 +9549,22 @@ index 00000000000..5f1c394ab3d +#include "asm/register.hpp" +#include "c1/c1_LIR.hpp" + -+FloatRegister LIR_Opr::as_float_reg() const { ++FloatRegister LIR_OprDesc::as_float_reg() const { + return as_FloatRegister(fpu_regnr()); +} + -+FloatRegister LIR_Opr::as_double_reg() const { ++FloatRegister LIR_OprDesc::as_double_reg() const { + return as_FloatRegister(fpu_regnrLo()); +} + +// Reg2 unused. +LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { + assert(as_FloatRegister(reg2) == fnoreg, "Not used on this platform"); -+ return (LIR_Opr)(intptr_t)((reg1 << LIR_Opr::reg1_shift) | -+ (reg1 << LIR_Opr::reg2_shift) | -+ LIR_Opr::double_type | -+ LIR_Opr::fpu_register | -+ LIR_Opr::double_size); ++ return (LIR_Opr)(intptr_t)((reg1 << LIR_OprDesc::reg1_shift) | ++ (reg1 << LIR_OprDesc::reg2_shift) | ++ LIR_OprDesc::double_type | ++ LIR_OprDesc::fpu_register | ++ LIR_OprDesc::double_size); +} + +#ifndef PRODUCT @@ -9749,7 +9577,7 @@ index 00000000000..5f1c394ab3d +#endif // PRODUCT diff --git a/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp new file mode 100644 -index 00000000000..78a61128bdd +index 0000000000..78a61128bd --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.cpp @@ -0,0 +1,33 @@ @@ -9788,7 +9616,7 @@ index 00000000000..78a61128bdd +} diff --git a/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp new file mode 100644 -index 00000000000..d7ca7b0fd05 +index 0000000000..d7ca7b0fd0 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LinearScan_riscv.hpp @@ -0,0 +1,83 @@ @@ -9877,10 +9705,10 @@ index 00000000000..d7ca7b0fd05 +#endif // CPU_RISCV_C1_LINEARSCAN_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp new file mode 100644 -index 00000000000..6f656c8c533 +index 0000000000..957bfa1127 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -0,0 +1,432 @@ +@@ -0,0 +1,444 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -9916,8 +9744,8 @@ index 00000000000..6f656c8c533 +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interpreter.hpp" +#include "oops/arrayOop.hpp" -+#include "oops/markWord.hpp" +#include "runtime/basicLock.hpp" ++#include "runtime/biasedLocking.hpp" +#include "runtime/os.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" @@ -9933,7 +9761,7 @@ index 00000000000..6f656c8c533 + } +} + -+int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) { ++int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register scratch, Label& slow_case) { + const int aligned_mask = BytesPerWord - 1; + const int hdr_offset = oopDesc::mark_offset_in_bytes(); + assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); @@ -9945,19 +9773,17 @@ index 00000000000..6f656c8c533 + // save object being locked into the BasicObjectLock + sd(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); + -+ null_check_offset = offset(); -+ -+ if (DiagnoseSyncOnValueBasedClasses != 0) { -+ load_klass(hdr, obj); -+ lwu(hdr, Address(hdr, Klass::access_flags_offset())); -+ andi(t0, hdr, JVM_ACC_IS_VALUE_BASED_CLASS); -+ bnez(t0, slow_case, true /* is_far */); ++ if (UseBiasedLocking) { ++ assert(scratch != noreg, "should have scratch register at this point"); ++ null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case); ++ } else { ++ null_check_offset = offset(); + } + + // Load object header + ld(hdr, Address(obj, hdr_offset)); + // and mark it as unlocked -+ ori(hdr, hdr, markWord::unlocked_value); ++ ori(hdr, hdr, markOopDesc::unlocked_value); + // save unlocked object header into the displaced header location on the stack + sd(hdr, Address(disp_hdr, 0)); + // test if object header is still the same (i.e. unlocked), and if so, store the @@ -9980,7 +9806,7 @@ index 00000000000..6f656c8c533 + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + sub(hdr, hdr, sp); -+ li(t0, aligned_mask - os::vm_page_size()); ++ mv(t0, aligned_mask - os::vm_page_size()); + andr(hdr, hdr, t0); + // for recursive locking, the result is zero => save it in the displaced header + // location (NULL in the displaced hdr location indicates recursive locking) @@ -9988,6 +9814,10 @@ index 00000000000..6f656c8c533 + // otherwise we don't care about the result and handle locking via runtime call + bnez(hdr, slow_case, /* is_far */ true); + bind(done); ++ if (PrintBiasedLockingStatistics) { ++ la(t1, ExternalAddress((address)BiasedLocking::fast_path_entry_count_addr())); ++ incrementw(Address(t1, 0)); ++ } + return null_check_offset; +} + @@ -9997,13 +9827,21 @@ index 00000000000..6f656c8c533 + assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); + Label done; + ++ if (UseBiasedLocking) { ++ // load object ++ ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); ++ biased_locking_exit(obj, hdr, done); ++ } ++ + // load displaced header + ld(hdr, Address(disp_hdr, 0)); + // if the loaded hdr is NULL we had recursive locking + // if we had recursive locking, we are done + beqz(hdr, done); -+ // load object -+ ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); ++ if (!UseBiasedLocking) { ++ // load object ++ ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); ++ } + verify_oop(obj); + // 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 @@ -10030,8 +9868,13 @@ index 00000000000..6f656c8c533 + +void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register tmp1, Register tmp2) { + assert_different_registers(obj, klass, len); -+ // This assumes that all prototype bits fitr in an int32_t -+ mv(tmp1, (int32_t)(intptr_t)markWord::prototype().value()); ++ if (UseBiasedLocking && !len->is_valid()) { ++ assert_different_registers(obj, klass, len, tmp1, tmp2); ++ ld(tmp1, Address(klass, Klass::prototype_header_offset())); ++ } else { ++ // This assumes that all prototype bits fitr in an int32_t ++ mv(tmp1, (int32_t)(intptr_t)markOopDesc::prototype()); ++ } + sd(tmp1, Address(obj, oopDesc::mark_offset_in_bytes())); + + if (UseCompressedClassPointers) { // Take care not to kill klass @@ -10185,15 +10028,17 @@ index 00000000000..6f656c8c533 +} + +void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { ++ // If we have to make this method not-entrant we'll overwrite its ++ // first instruction with a jump. For this action to be legal we ++ // must ensure that this first instruction is a J, JAL or NOP. ++ // Make it a NOP. ++ nop(); ++ + assert(bang_size_in_bytes >= framesize, "stack bang size incorrect"); + // Make sure there is enough stack space for this method's activation. + // Note that we do this before creating a frame. + generate_stack_overflow_check(bang_size_in_bytes); + MacroAssembler::build_frame(framesize); -+ -+ // Insert nmethod entry barrier into frame. -+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ bs->nmethod_entry_barrier(this); +} + +void C1_MacroAssembler::remove_frame(int framesize) { @@ -10201,13 +10046,8 @@ index 00000000000..6f656c8c533 +} + + -+void C1_MacroAssembler::verified_entry(bool breakAtEntry) { -+ // If we have to make this method not-entrant we'll overwrite its -+ // first instruction with a jump. For this action to be legal we -+ // must ensure that this first instruction is a J, JAL or NOP. -+ // Make it a NOP. -+ -+ nop(); ++void C1_MacroAssembler::verified_entry() { ++ assert_alignment(pc()); +} + +void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) { @@ -10315,10 +10155,10 @@ index 00000000000..6f656c8c533 +} diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp new file mode 100644 -index 00000000000..dfd3c17d7c7 +index 0000000000..1950cee5dd --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp -@@ -0,0 +1,120 @@ +@@ -0,0 +1,121 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. @@ -10380,8 +10220,9 @@ index 00000000000..dfd3c17d7c7 + // hdr : must be x10, contents destroyed + // obj : must point to the object to lock, contents preserved + // disp_hdr: must point to the displaced header location, contents preserved ++ // scratch : scratch register, contents destroyed + // returns code offset at which to add null check debug information -+ int lock_object (Register swap, Register obj, Register disp_hdr, Label& slow_case); ++ int lock_object (Register swap, Register obj, Register disp_hdr, Register scratch, Label& slow_case); + + // unlocking + // hdr : contents destroyed @@ -10441,10 +10282,10 @@ index 00000000000..dfd3c17d7c7 +#endif // CPU_RISCV_C1_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp new file mode 100644 -index 00000000000..f523c9ed50a +index 0000000000..ffcca64e0b --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -@@ -0,0 +1,1172 @@ +@@ -0,0 +1,1210 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -10493,7 +10334,6 @@ index 00000000000..f523c9ed50a +#include "runtime/stubRoutines.hpp" +#include "runtime/vframe.hpp" +#include "runtime/vframeArray.hpp" -+#include "utilities/powerOfTwo.hpp" +#include "vmreg_riscv.inline.hpp" + + @@ -10614,19 +10454,14 @@ index 00000000000..f523c9ed50a + return call_RT(oop_result, metadata_result, entry, arg_num); +} + -+enum return_state_t { -+ does_not_return, requires_return -+}; -+ +// Implementation of StubFrame + +class StubFrame: public StackObj { + private: + StubAssembler* _sasm; -+ bool _return_state; + + public: -+ StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state=requires_return); ++ StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); + void load_argument(int offset_in_words, Register reg); + + ~StubFrame(); @@ -10644,9 +10479,8 @@ index 00000000000..f523c9ed50a + +#define __ _sasm-> + -+StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state) { ++StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { + _sasm = sasm; -+ _return_state = return_state; + __ prologue(name, must_gc_arguments); +} + @@ -10658,11 +10492,7 @@ index 00000000000..f523c9ed50a + + +StubFrame::~StubFrame() { -+ if (_return_state == requires_return) { -+ __ epilogue(); -+ } else { -+ __ should_not_reach_here(); -+ } ++ __ epilogue(); + _sasm = NULL; +} + @@ -10825,6 +10655,7 @@ index 00000000000..f523c9ed50a + assert_cond(oop_maps != NULL); + oop_maps->add_gc_map(call_offset, oop_map); + ++ __ should_not_reach_here(); + return oop_maps; +} + @@ -10872,7 +10703,9 @@ index 00000000000..f523c9ed50a + sasm->set_frame_size(frame_size); + break; + } -+ default: ShouldNotReachHere(); ++ default: ++ __ should_not_reach_here(); ++ break; + } + + // verify that only x10 and x13 are valid at this time @@ -10928,6 +10761,9 @@ index 00000000000..f523c9ed50a + restore_live_registers(sasm, id != handle_exception_nofpu_id); + break; + case handle_exception_from_callee_id: ++ // Pop the return address. ++ __ leave(); ++ __ ret(); // jump to exception handler + break; + default: ShouldNotReachHere(); + } @@ -11032,37 +10868,80 @@ index 00000000000..f523c9ed50a +#endif + __ reset_last_Java_frame(true); + -+#ifdef ASSERT -+ // Check that fields in JavaThread for exception oop and issuing pc are empty -+ Label oop_empty; -+ __ ld(t0, Address(xthread, Thread::pending_exception_offset())); -+ __ beqz(t0, oop_empty); -+ __ stop("exception oop must be empty"); -+ __ bind(oop_empty); ++ // check for pending exceptions ++ { Label L; ++ __ ld(t0, Address(xthread, Thread::pending_exception_offset())); ++ __ beqz(t0, L); ++ // exception pending => remove activation and forward to exception handler + -+ Label pc_empty; -+ __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); -+ __ beqz(t0, pc_empty); -+ __ stop("exception pc must be empty"); -+ __ bind(pc_empty); ++ { Label L1; ++ __ bnez(x10, L1); // have we deoptimized? ++ __ far_jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); ++ __ bind(L1); ++ } ++ ++ // the deopt blob expects exceptions in the special fields of ++ // JavaThread, so copy and clear pending exception. ++ ++ // load and clear pending exception ++ __ ld(x10, Address(xthread, Thread::pending_exception_offset())); ++ __ sd(zr, Address(xthread, Thread::pending_exception_offset())); ++ ++ // check that there is really a valid exception ++ __ verify_not_null_oop(x10); ++ ++ // load throwing pc: this is the return address of the stub ++ __ ld(x13, Address(fp, wordSize)); ++ ++#ifdef ASSERT ++ // Check that fields in JavaThread for exception oop and issuing pc are empty ++ Label oop_empty; ++ __ ld(t0, Address(xthread, Thread::pending_exception_offset())); ++ __ beqz(t0, oop_empty); ++ __ stop("exception oop must be empty"); ++ __ bind(oop_empty); ++ ++ Label pc_empty; ++ __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); ++ __ beqz(t0, pc_empty); ++ __ stop("exception pc must be empty"); ++ __ bind(pc_empty); +#endif + -+ // Runtime will return true if the nmethod has been deoptimized, this is the -+ // expected scenario and anything else is an error. Note that we maintain a -+ // check on the result purely as a defensive measure. -+ Label no_deopt; -+ __ beqz(x10, no_deopt); // Have we deoptimized? ++ // store exception oop and throwing pc to JavaThread ++ __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); ++ __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); + -+ // Perform a re-execute. The proper return address is already on the stack, -+ // we just need to restore registers, pop all of our frames but the return -+ // address and jump to the deopt blob. ++ restore_live_registers(sasm); ++ ++ __ leave(); ++ ++ // Forward the exception directly to deopt blob. We can blow no ++ // registers and must leave throwing pc on the stack. A patch may ++ // have values live in registers so the entry point with the ++ // exception in tls. ++ __ far_jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls())); ++ ++ __ bind(L); ++ } ++ ++ // Runtime will return true if the nmethod has been deoptimized during ++ // the patching process. In that case we must do a deopt reexecute instead. ++ Label cont; ++ ++ __ beqz(x10, cont); // have we deoptimized? ++ ++ // Will reexecute. Proper return address is already on the stack we just restore ++ // registers, pop all of our frame but the return address and jump to the deopt blob + + restore_live_registers(sasm); + __ leave(); + __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); + -+ __ bind(no_deopt); -+ __ stop("deopt not performed"); ++ __ bind(cont); ++ restore_live_registers(sasm); ++ __ leave(); ++ __ ret(); + + return oop_maps; +} @@ -11088,13 +10967,13 @@ index 00000000000..f523c9ed50a + + case throw_div0_exception_id: + { -+ StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); + } + break; + + case throw_null_pointer_exception_id: -+ { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments, does_not_return); ++ { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); + } + break; @@ -11373,14 +11252,14 @@ index 00000000000..f523c9ed50a + + case throw_class_cast_exception_id: + { -+ StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); + } + break; + + case throw_incompatible_class_change_error_id: + { -+ StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, + CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); + } @@ -11414,7 +11293,7 @@ index 00000000000..f523c9ed50a + __ check_klass_subtype_slow_path(x14, x10, x12, x15, NULL, &miss); + + // fallthrough on success: -+ __ li(t0, 1); ++ __ mv(t0, 1); + __ sd(t0, Address(sp, (result_off) * VMRegImpl::stack_slot_size)); // result + __ pop_reg(RegSet::of(x10, x12, x14, x15), sp); + __ ret(); @@ -11474,7 +11353,7 @@ index 00000000000..f523c9ed50a + + case deoptimize_id: + { -+ StubFrame f(sasm, "deoptimize", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "deoptimize", dont_gc_arguments); + OopMap* oop_map = save_live_registers(sasm); + assert_cond(oop_map != NULL); + f.load_argument(0, c_rarg1); @@ -11493,7 +11372,7 @@ index 00000000000..f523c9ed50a + + case throw_range_check_failed_id: + { -+ StubFrame f(sasm, "range_check_failed", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "range_check_failed", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); + } + break; @@ -11509,7 +11388,7 @@ index 00000000000..f523c9ed50a + + case access_field_patching_id: + { -+ StubFrame f(sasm, "access_field_patching", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "access_field_patching", dont_gc_arguments); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); + } @@ -11517,7 +11396,7 @@ index 00000000000..f523c9ed50a + + case load_klass_patching_id: + { -+ StubFrame f(sasm, "load_klass_patching", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "load_klass_patching", dont_gc_arguments); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); + } @@ -11525,7 +11404,7 @@ index 00000000000..f523c9ed50a + + case load_mirror_patching_id: + { -+ StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); + } @@ -11533,7 +11412,7 @@ index 00000000000..f523c9ed50a + + case load_appendix_patching_id: + { -+ StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); + } @@ -11556,14 +11435,14 @@ index 00000000000..f523c9ed50a + + case throw_index_exception_id: + { -+ StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); + } + break; + + case throw_array_store_exception_id: + { -+ StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); + // tos + 0: link + // + 1: return address + oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); @@ -11572,7 +11451,7 @@ index 00000000000..f523c9ed50a + + case predicate_failed_trap_id: + { -+ StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments, does_not_return); ++ StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); + + OopMap* map = save_live_registers(sasm); + assert_cond(map != NULL); @@ -11595,7 +11474,7 @@ index 00000000000..f523c9ed50a + StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); + save_live_registers(sasm); + -+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), c_rarg0); ++ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), c_rarg0); + + restore_live_registers(sasm); + } @@ -11603,8 +11482,8 @@ index 00000000000..f523c9ed50a + + default: + { -+ StubFrame f(sasm, "unimplemented entry", dont_gc_arguments, does_not_return); -+ __ li(x10, (int) id); ++ StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); ++ __ mv(x10, (int)id); + __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), x10); + __ should_not_reach_here(); + } @@ -11619,10 +11498,10 @@ index 00000000000..f523c9ed50a +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp new file mode 100644 -index 00000000000..fe46f7b21c8 +index 0000000000..9316d4be02 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -0,0 +1,65 @@ +@@ -0,0 +1,71 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -11657,8 +11536,10 @@ index 00000000000..fe46f7b21c8 +// Sets the default values for platform dependent flags used by the client compiler. +// (see c1_globals.hpp) + -+#ifndef COMPILER2 ++#ifndef TIERED +define_pd_global(bool, BackgroundCompilation, true ); ++define_pd_global(bool, UseTLAB, true ); ++define_pd_global(bool, ResizeTLAB, true ); +define_pd_global(bool, InlineIntrinsics, true ); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, false); @@ -11667,6 +11548,7 @@ index 00000000000..fe46f7b21c8 +define_pd_global(intx, CompileThreshold, 1500 ); + +define_pd_global(intx, OnStackReplacePercentage, 933 ); ++define_pd_global(intx, FreqInlineSize, 325 ); +define_pd_global(intx, NewSizeThreadIncrease, 4*K ); +define_pd_global(intx, InitialCodeCacheSize, 160*K); +define_pd_global(intx, ReservedCodeCacheSize, 32*M ); @@ -11677,1874 +11559,26 @@ index 00000000000..fe46f7b21c8 +define_pd_global(intx, CodeCacheExpansionSize, 32*K ); +define_pd_global(uintx, CodeCacheMinBlockLength, 1); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); ++define_pd_global(uintx, MetaspaceSize, 12*M ); +define_pd_global(bool, NeverActAsServerClassMachine, true ); -+define_pd_global(uint64_t, MaxRAM, 1ULL*G); ++define_pd_global(uint64_t, MaxRAM, 1ULL*G); +define_pd_global(bool, CICompileOSR, true ); -+#endif // !COMPILER2 ++#endif // !TIERED +define_pd_global(bool, UseTypeProfile, false); ++define_pd_global(bool, RoundFPResults, true ); + ++define_pd_global(bool, LIRFillDelaySlots, false); +define_pd_global(bool, OptimizeSinglePrecision, true ); +define_pd_global(bool, CSEArrayLength, false); +define_pd_global(bool, TwoOperandLIRForm, false); + +#endif // CPU_RISCV_C1_GLOBALS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -new file mode 100644 -index 00000000000..27770dc17aa ---- /dev/null -+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -@@ -0,0 +1,1646 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "asm/assembler.hpp" -+#include "asm/assembler.inline.hpp" -+#include "opto/c2_MacroAssembler.hpp" -+#include "opto/intrinsicnode.hpp" -+#include "opto/subnode.hpp" -+#include "runtime/stubRoutines.hpp" -+ -+#ifdef PRODUCT -+#define BLOCK_COMMENT(str) /* nothing */ -+#define STOP(error) stop(error) -+#else -+#define BLOCK_COMMENT(str) block_comment(str) -+#define STOP(error) block_comment(error); stop(error) -+#endif -+ -+#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -+ -+// short string -+// StringUTF16.indexOfChar -+// StringLatin1.indexOfChar -+void C2_MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, -+ Register ch, Register result, -+ bool isL) -+{ -+ Register ch1 = t0; -+ Register index = t1; -+ -+ BLOCK_COMMENT("string_indexof_char_short {"); -+ -+ Label LOOP, LOOP1, LOOP4, LOOP8; -+ Label MATCH, MATCH1, MATCH2, MATCH3, -+ MATCH4, MATCH5, MATCH6, MATCH7, NOMATCH; -+ -+ mv(result, -1); -+ mv(index, zr); -+ -+ bind(LOOP); -+ addi(t0, index, 8); -+ ble(t0, cnt1, LOOP8); -+ addi(t0, index, 4); -+ ble(t0, cnt1, LOOP4); -+ j(LOOP1); -+ -+ bind(LOOP8); -+ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -+ beq(ch, ch1, MATCH); -+ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -+ beq(ch, ch1, MATCH1); -+ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -+ beq(ch, ch1, MATCH2); -+ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -+ beq(ch, ch1, MATCH3); -+ isL ? lbu(ch1, Address(str1, 4)) : lhu(ch1, Address(str1, 8)); -+ beq(ch, ch1, MATCH4); -+ isL ? lbu(ch1, Address(str1, 5)) : lhu(ch1, Address(str1, 10)); -+ beq(ch, ch1, MATCH5); -+ isL ? lbu(ch1, Address(str1, 6)) : lhu(ch1, Address(str1, 12)); -+ beq(ch, ch1, MATCH6); -+ isL ? lbu(ch1, Address(str1, 7)) : lhu(ch1, Address(str1, 14)); -+ beq(ch, ch1, MATCH7); -+ addi(index, index, 8); -+ addi(str1, str1, isL ? 8 : 16); -+ blt(index, cnt1, LOOP); -+ j(NOMATCH); -+ -+ bind(LOOP4); -+ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -+ beq(ch, ch1, MATCH); -+ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -+ beq(ch, ch1, MATCH1); -+ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -+ beq(ch, ch1, MATCH2); -+ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -+ beq(ch, ch1, MATCH3); -+ addi(index, index, 4); -+ addi(str1, str1, isL ? 4 : 8); -+ bge(index, cnt1, NOMATCH); -+ -+ bind(LOOP1); -+ isL ? lbu(ch1, Address(str1)) : lhu(ch1, Address(str1)); -+ beq(ch, ch1, MATCH); -+ addi(index, index, 1); -+ addi(str1, str1, isL ? 1 : 2); -+ blt(index, cnt1, LOOP1); -+ j(NOMATCH); -+ -+ bind(MATCH1); -+ addi(index, index, 1); -+ j(MATCH); -+ -+ bind(MATCH2); -+ addi(index, index, 2); -+ j(MATCH); -+ -+ bind(MATCH3); -+ addi(index, index, 3); -+ j(MATCH); -+ -+ bind(MATCH4); -+ addi(index, index, 4); -+ j(MATCH); -+ -+ bind(MATCH5); -+ addi(index, index, 5); -+ j(MATCH); -+ -+ bind(MATCH6); -+ addi(index, index, 6); -+ j(MATCH); -+ -+ bind(MATCH7); -+ addi(index, index, 7); -+ -+ bind(MATCH); -+ mv(result, index); -+ bind(NOMATCH); -+ BLOCK_COMMENT("} string_indexof_char_short"); -+} -+ -+// StringUTF16.indexOfChar -+// StringLatin1.indexOfChar -+void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ bool isL) -+{ -+ Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; -+ Register ch1 = t0; -+ Register orig_cnt = t1; -+ Register mask1 = tmp3; -+ Register mask2 = tmp2; -+ Register match_mask = tmp1; -+ Register trailing_char = tmp4; -+ Register unaligned_elems = tmp4; -+ -+ BLOCK_COMMENT("string_indexof_char {"); -+ beqz(cnt1, NOMATCH); -+ -+ addi(t0, cnt1, isL ? -32 : -16); -+ bgtz(t0, DO_LONG); -+ string_indexof_char_short(str1, cnt1, ch, result, isL); -+ j(DONE); -+ -+ bind(DO_LONG); -+ mv(orig_cnt, cnt1); -+ if (AvoidUnalignedAccesses) { -+ Label ALIGNED; -+ andi(unaligned_elems, str1, 0x7); -+ beqz(unaligned_elems, ALIGNED); -+ sub(unaligned_elems, unaligned_elems, 8); -+ neg(unaligned_elems, unaligned_elems); -+ if (!isL) { -+ srli(unaligned_elems, unaligned_elems, 1); -+ } -+ // do unaligned part per element -+ string_indexof_char_short(str1, unaligned_elems, ch, result, isL); -+ bgez(result, DONE); -+ mv(orig_cnt, cnt1); -+ sub(cnt1, cnt1, unaligned_elems); -+ bind(ALIGNED); -+ } -+ -+ // duplicate ch -+ if (isL) { -+ slli(ch1, ch, 8); -+ orr(ch, ch1, ch); -+ } -+ slli(ch1, ch, 16); -+ orr(ch, ch1, ch); -+ slli(ch1, ch, 32); -+ orr(ch, ch1, ch); -+ -+ if (!isL) { -+ slli(cnt1, cnt1, 1); -+ } -+ -+ uint64_t mask0101 = UCONST64(0x0101010101010101); -+ uint64_t mask0001 = UCONST64(0x0001000100010001); -+ mv(mask1, isL ? mask0101 : mask0001); -+ uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); -+ uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); -+ mv(mask2, isL ? mask7f7f : mask7fff); -+ -+ bind(CH1_LOOP); -+ ld(ch1, Address(str1)); -+ addi(str1, str1, 8); -+ addi(cnt1, cnt1, -8); -+ compute_match_mask(ch1, ch, match_mask, mask1, mask2); -+ bnez(match_mask, HIT); -+ bgtz(cnt1, CH1_LOOP); -+ j(NOMATCH); -+ -+ bind(HIT); -+ ctzc_bit(trailing_char, match_mask, isL, ch1, result); -+ srli(trailing_char, trailing_char, 3); -+ addi(cnt1, cnt1, 8); -+ ble(cnt1, trailing_char, NOMATCH); -+ // match case -+ if (!isL) { -+ srli(cnt1, cnt1, 1); -+ srli(trailing_char, trailing_char, 1); -+ } -+ -+ sub(result, orig_cnt, cnt1); -+ add(result, result, trailing_char); -+ j(DONE); -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} string_indexof_char"); -+} -+ -+typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); -+ -+// Search for needle in haystack and return index or -1 -+// x10: result -+// x11: haystack -+// x12: haystack_len -+// x13: needle -+// x14: needle_len -+void C2_MacroAssembler::string_indexof(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, int ae) -+{ -+ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -+ -+ Label LINEARSEARCH, LINEARSTUB, DONE, NOMATCH; -+ -+ Register ch1 = t0; -+ Register ch2 = t1; -+ Register nlen_tmp = tmp1; // needle len tmp -+ Register hlen_tmp = tmp2; // haystack len tmp -+ Register result_tmp = tmp4; -+ -+ bool isLL = ae == StrIntrinsicNode::LL; -+ -+ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -+ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -+ int needle_chr_shift = needle_isL ? 0 : 1; -+ int haystack_chr_shift = haystack_isL ? 0 : 1; -+ int needle_chr_size = needle_isL ? 1 : 2; -+ int haystack_chr_size = haystack_isL ? 1 : 2; -+ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ -+ BLOCK_COMMENT("string_indexof {"); -+ -+ // Note, inline_string_indexOf() generates checks: -+ // if (pattern.count > src.count) return -1; -+ // if (pattern.count == 0) return 0; -+ -+ // We have two strings, a source string in haystack, haystack_len and a pattern string -+ // in needle, needle_len. Find the first occurence of pattern in source or return -1. -+ -+ // For larger pattern and source we use a simplified Boyer Moore algorithm. -+ // With a small pattern and source we use linear scan. -+ -+ // needle_len >=8 && needle_len < 256 && needle_len < haystack_len/4, use bmh algorithm. -+ sub(result_tmp, haystack_len, needle_len); -+ // needle_len < 8, use linear scan -+ sub(t0, needle_len, 8); -+ bltz(t0, LINEARSEARCH); -+ // needle_len >= 256, use linear scan -+ sub(t0, needle_len, 256); -+ bgez(t0, LINEARSTUB); -+ // needle_len >= haystack_len/4, use linear scan -+ srli(t0, haystack_len, 2); -+ bge(needle_len, t0, LINEARSTUB); -+ -+ // Boyer-Moore-Horspool introduction: -+ // The Boyer Moore alogorithm is based on the description here:- -+ // -+ // http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm -+ // -+ // This describes and algorithm with 2 shift rules. The 'Bad Character' rule -+ // and the 'Good Suffix' rule. -+ // -+ // These rules are essentially heuristics for how far we can shift the -+ // pattern along the search string. -+ // -+ // The implementation here uses the 'Bad Character' rule only because of the -+ // complexity of initialisation for the 'Good Suffix' rule. -+ // -+ // This is also known as the Boyer-Moore-Horspool algorithm: -+ // -+ // http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm -+ // -+ // #define ASIZE 256 -+ // -+ // int bm(unsigned char *pattern, int m, unsigned char *src, int n) { -+ // int i, j; -+ // unsigned c; -+ // unsigned char bc[ASIZE]; -+ // -+ // /* Preprocessing */ -+ // for (i = 0; i < ASIZE; ++i) -+ // bc[i] = m; -+ // for (i = 0; i < m - 1; ) { -+ // c = pattern[i]; -+ // ++i; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef PATTERN_STRING_IS_LATIN1 -+ // bc[c] = m - i; -+ // #else -+ // if (c < ASIZE) bc[c] = m - i; -+ // #endif -+ // } -+ // -+ // /* Searching */ -+ // j = 0; -+ // while (j <= n - m) { -+ // c = src[i+j]; -+ // if (pattern[m-1] == c) -+ // int k; -+ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -+ // if (k < 0) return j; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef SOURCE_STRING_IS_LATIN1_AND_PATTERN_STRING_IS_LATIN1 -+ // // LL case: (c< 256) always true. Remove branch -+ // j += bc[pattern[j+m-1]]; -+ // #endif -+ // #ifdef SOURCE_STRING_IS_UTF_AND_PATTERN_STRING_IS_UTF -+ // // UU case: need if (c if not. -+ // if (c < ASIZE) -+ // j += bc[pattern[j+m-1]]; -+ // else -+ // j += m -+ // #endif -+ // } -+ // return -1; -+ // } -+ -+ // temp register:t0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, result -+ Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH, -+ BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP; -+ -+ Register haystack_end = haystack_len; -+ Register skipch = tmp2; -+ -+ // pattern length is >=8, so, we can read at least 1 register for cases when -+ // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for -+ // UL case. We'll re-read last character in inner pre-loop code to have -+ // single outer pre-loop load -+ const int firstStep = isLL ? 7 : 3; -+ -+ const int ASIZE = 256; -+ const int STORE_BYTES = 8; // 8 bytes stored per instruction(sd) -+ -+ sub(sp, sp, ASIZE); -+ -+ // init BC offset table with default value: needle_len -+ slli(t0, needle_len, 8); -+ orr(t0, t0, needle_len); // [63...16][needle_len][needle_len] -+ slli(tmp1, t0, 16); -+ orr(t0, tmp1, t0); // [63...32][needle_len][needle_len][needle_len][needle_len] -+ slli(tmp1, t0, 32); -+ orr(tmp5, tmp1, t0); // tmp5: 8 elements [needle_len] -+ -+ mv(ch1, sp); // ch1 is t0 -+ mv(tmp6, ASIZE / STORE_BYTES); // loop iterations -+ -+ bind(BM_INIT_LOOP); -+ // for (i = 0; i < ASIZE; ++i) -+ // bc[i] = m; -+ for (int i = 0; i < 4; i++) { -+ sd(tmp5, Address(ch1, i * wordSize)); -+ } -+ add(ch1, ch1, 32); -+ sub(tmp6, tmp6, 4); -+ bgtz(tmp6, BM_INIT_LOOP); -+ -+ sub(nlen_tmp, needle_len, 1); // m - 1, index of the last element in pattern -+ Register orig_haystack = tmp5; -+ mv(orig_haystack, haystack); -+ // result_tmp = tmp4 -+ shadd(haystack_end, result_tmp, haystack, haystack_end, haystack_chr_shift); -+ sub(ch2, needle_len, 1); // bc offset init value, ch2 is t1 -+ mv(tmp3, needle); -+ -+ // for (i = 0; i < m - 1; ) { -+ // c = pattern[i]; -+ // ++i; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef PATTERN_STRING_IS_LATIN1 -+ // bc[c] = m - i; -+ // #else -+ // if (c < ASIZE) bc[c] = m - i; -+ // #endif -+ // } -+ bind(BCLOOP); -+ (this->*needle_load_1chr)(ch1, Address(tmp3), noreg); -+ add(tmp3, tmp3, needle_chr_size); -+ if (!needle_isL) { -+ // ae == StrIntrinsicNode::UU -+ mv(tmp6, ASIZE); -+ bgeu(ch1, tmp6, BCSKIP); -+ } -+ add(tmp4, sp, ch1); -+ sb(ch2, Address(tmp4)); // store skip offset to BC offset table -+ -+ bind(BCSKIP); -+ sub(ch2, ch2, 1); // for next pattern element, skip distance -1 -+ bgtz(ch2, BCLOOP); -+ -+ // tmp6: pattern end, address after needle -+ shadd(tmp6, needle_len, needle, tmp6, needle_chr_shift); -+ if (needle_isL == haystack_isL) { -+ // load last 8 bytes (8LL/4UU symbols) -+ ld(tmp6, Address(tmp6, -wordSize)); -+ } else { -+ // UL: from UTF-16(source) search Latin1(pattern) -+ lwu(tmp6, Address(tmp6, -wordSize / 2)); // load last 4 bytes(4 symbols) -+ // convert Latin1 to UTF. eg: 0x0000abcd -> 0x0a0b0c0d -+ // We'll have to wait until load completed, but it's still faster than per-character loads+checks -+ srli(tmp3, tmp6, BitsPerByte * (wordSize / 2 - needle_chr_size)); // pattern[m-1], eg:0x0000000a -+ slli(ch2, tmp6, XLEN - 24); -+ srli(ch2, ch2, XLEN - 8); // pattern[m-2], 0x0000000b -+ slli(ch1, tmp6, XLEN - 16); -+ srli(ch1, ch1, XLEN - 8); // pattern[m-3], 0x0000000c -+ andi(tmp6, tmp6, 0xff); // pattern[m-4], 0x0000000d -+ slli(ch2, ch2, 16); -+ orr(ch2, ch2, ch1); // 0x00000b0c -+ slli(result, tmp3, 48); // use result as temp register -+ orr(tmp6, tmp6, result); // 0x0a00000d -+ slli(result, ch2, 16); -+ orr(tmp6, tmp6, result); // UTF-16:0x0a0b0c0d -+ } -+ -+ // i = m - 1; -+ // skipch = j + i; -+ // if (skipch == pattern[m - 1] -+ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -+ // else -+ // move j with bad char offset table -+ bind(BMLOOPSTR2); -+ // compare pattern to source string backward -+ shadd(result, nlen_tmp, haystack, result, haystack_chr_shift); -+ (this->*haystack_load_1chr)(skipch, Address(result), noreg); -+ sub(nlen_tmp, nlen_tmp, firstStep); // nlen_tmp is positive here, because needle_len >= 8 -+ if (needle_isL == haystack_isL) { -+ // re-init tmp3. It's for free because it's executed in parallel with -+ // load above. Alternative is to initialize it before loop, but it'll -+ // affect performance on in-order systems with 2 or more ld/st pipelines -+ srli(tmp3, tmp6, BitsPerByte * (wordSize - needle_chr_size)); // UU/LL: pattern[m-1] -+ } -+ if (!isLL) { // UU/UL case -+ slli(ch2, nlen_tmp, 1); // offsets in bytes -+ } -+ bne(tmp3, skipch, BMSKIP); // if not equal, skipch is bad char -+ add(result, haystack, isLL ? nlen_tmp : ch2); -+ ld(ch2, Address(result)); // load 8 bytes from source string -+ mv(ch1, tmp6); -+ if (isLL) { -+ j(BMLOOPSTR1_AFTER_LOAD); -+ } else { -+ sub(nlen_tmp, nlen_tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8 -+ j(BMLOOPSTR1_CMP); -+ } -+ -+ bind(BMLOOPSTR1); -+ shadd(ch1, nlen_tmp, needle, ch1, needle_chr_shift); -+ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -+ shadd(ch2, nlen_tmp, haystack, ch2, haystack_chr_shift); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ -+ bind(BMLOOPSTR1_AFTER_LOAD); -+ sub(nlen_tmp, nlen_tmp, 1); -+ bltz(nlen_tmp, BMLOOPSTR1_LASTCMP); -+ -+ bind(BMLOOPSTR1_CMP); -+ beq(ch1, ch2, BMLOOPSTR1); -+ -+ bind(BMSKIP); -+ if (!isLL) { -+ // if we've met UTF symbol while searching Latin1 pattern, then we can -+ // skip needle_len symbols -+ if (needle_isL != haystack_isL) { -+ mv(result_tmp, needle_len); -+ } else { -+ mv(result_tmp, 1); -+ } -+ mv(t0, ASIZE); -+ bgeu(skipch, t0, BMADV); -+ } -+ add(result_tmp, sp, skipch); -+ lbu(result_tmp, Address(result_tmp)); // load skip offset -+ -+ bind(BMADV); -+ sub(nlen_tmp, needle_len, 1); -+ // move haystack after bad char skip offset -+ shadd(haystack, result_tmp, haystack, result, haystack_chr_shift); -+ ble(haystack, haystack_end, BMLOOPSTR2); -+ add(sp, sp, ASIZE); -+ j(NOMATCH); -+ -+ bind(BMLOOPSTR1_LASTCMP); -+ bne(ch1, ch2, BMSKIP); -+ -+ bind(BMMATCH); -+ sub(result, haystack, orig_haystack); -+ if (!haystack_isL) { -+ srli(result, result, 1); -+ } -+ add(sp, sp, ASIZE); -+ j(DONE); -+ -+ bind(LINEARSTUB); -+ sub(t0, needle_len, 16); // small patterns still should be handled by simple algorithm -+ bltz(t0, LINEARSEARCH); -+ mv(result, zr); -+ RuntimeAddress stub = NULL; -+ if (isLL) { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ll()); -+ assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated"); -+ } else if (needle_isL) { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ul()); -+ assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated"); -+ } else { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); -+ assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); -+ } -+ trampoline_call(stub); -+ j(DONE); -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ j(DONE); -+ -+ bind(LINEARSEARCH); -+ string_indexof_linearscan(haystack, needle, haystack_len, needle_len, tmp1, tmp2, tmp3, tmp4, -1, result, ae); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} string_indexof"); -+} -+ -+// string_indexof -+// result: x10 -+// src: x11 -+// src_count: x12 -+// pattern: x13 -+// pattern_count: x14 or 1/2/3/4 -+void C2_MacroAssembler::string_indexof_linearscan(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ int needle_con_cnt, Register result, int ae) -+{ -+ // Note: -+ // needle_con_cnt > 0 means needle_len register is invalid, needle length is constant -+ // for UU/LL: needle_con_cnt[1, 4], UL: needle_con_cnt = 1 -+ assert(needle_con_cnt <= 4, "Invalid needle constant count"); -+ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -+ -+ Register ch1 = t0; -+ Register ch2 = t1; -+ Register hlen_neg = haystack_len, nlen_neg = needle_len; -+ Register nlen_tmp = tmp1, hlen_tmp = tmp2, result_tmp = tmp4; -+ -+ bool isLL = ae == StrIntrinsicNode::LL; -+ -+ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -+ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -+ int needle_chr_shift = needle_isL ? 0 : 1; -+ int haystack_chr_shift = haystack_isL ? 0 : 1; -+ int needle_chr_size = needle_isL ? 1 : 2; -+ int haystack_chr_size = haystack_isL ? 1 : 2; -+ -+ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn load_2chr = isLL ? (load_chr_insn)&MacroAssembler::lhu : (load_chr_insn)&MacroAssembler::lwu; -+ load_chr_insn load_4chr = isLL ? (load_chr_insn)&MacroAssembler::lwu : (load_chr_insn)&MacroAssembler::ld; -+ -+ Label DO1, DO2, DO3, MATCH, NOMATCH, DONE; -+ -+ Register first = tmp3; -+ -+ if (needle_con_cnt == -1) { -+ Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT; -+ -+ sub(t0, needle_len, needle_isL == haystack_isL ? 4 : 2); -+ bltz(t0, DOSHORT); -+ -+ (this->*needle_load_1chr)(first, Address(needle), noreg); -+ slli(t0, needle_len, needle_chr_shift); -+ add(needle, needle, t0); -+ neg(nlen_neg, t0); -+ slli(t0, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, t0); -+ neg(hlen_neg, t0); -+ -+ bind(FIRST_LOOP); -+ add(t0, haystack, hlen_neg); -+ (this->*haystack_load_1chr)(ch2, Address(t0), noreg); -+ beq(first, ch2, STR1_LOOP); -+ -+ bind(STR2_NEXT); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, FIRST_LOOP); -+ j(NOMATCH); -+ -+ bind(STR1_LOOP); -+ add(nlen_tmp, nlen_neg, needle_chr_size); -+ add(hlen_tmp, hlen_neg, haystack_chr_size); -+ bgez(nlen_tmp, MATCH); -+ -+ bind(STR1_NEXT); -+ add(ch1, needle, nlen_tmp); -+ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -+ add(ch2, haystack, hlen_tmp); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ bne(ch1, ch2, STR2_NEXT); -+ add(nlen_tmp, nlen_tmp, needle_chr_size); -+ add(hlen_tmp, hlen_tmp, haystack_chr_size); -+ bltz(nlen_tmp, STR1_NEXT); -+ j(MATCH); -+ -+ bind(DOSHORT); -+ if (needle_isL == haystack_isL) { -+ sub(t0, needle_len, 2); -+ bltz(t0, DO1); -+ bgtz(t0, DO3); -+ } -+ } -+ -+ if (needle_con_cnt == 4) { -+ Label CH1_LOOP; -+ (this->*load_4chr)(ch1, Address(needle), noreg); -+ sub(result_tmp, haystack_len, 4); -+ slli(tmp3, result_tmp, haystack_chr_shift); // result as tmp -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(CH1_LOOP); -+ add(ch2, haystack, hlen_neg); -+ (this->*load_4chr)(ch2, Address(ch2), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, CH1_LOOP); -+ j(NOMATCH); -+ } -+ -+ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 2) { -+ Label CH1_LOOP; -+ BLOCK_COMMENT("string_indexof DO2 {"); -+ bind(DO2); -+ (this->*load_2chr)(ch1, Address(needle), noreg); -+ if (needle_con_cnt == 2) { -+ sub(result_tmp, haystack_len, 2); -+ } -+ slli(tmp3, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(CH1_LOOP); -+ add(tmp3, haystack, hlen_neg); -+ (this->*load_2chr)(ch2, Address(tmp3), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, CH1_LOOP); -+ j(NOMATCH); -+ BLOCK_COMMENT("} string_indexof DO2"); -+ } -+ -+ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 3) { -+ Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; -+ BLOCK_COMMENT("string_indexof DO3 {"); -+ -+ bind(DO3); -+ (this->*load_2chr)(first, Address(needle), noreg); -+ (this->*needle_load_1chr)(ch1, Address(needle, 2 * needle_chr_size), noreg); -+ if (needle_con_cnt == 3) { -+ sub(result_tmp, haystack_len, 3); -+ } -+ slli(hlen_tmp, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, hlen_tmp); -+ neg(hlen_neg, hlen_tmp); -+ -+ bind(FIRST_LOOP); -+ add(ch2, haystack, hlen_neg); -+ (this->*load_2chr)(ch2, Address(ch2), noreg); -+ beq(first, ch2, STR1_LOOP); -+ -+ bind(STR2_NEXT); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, FIRST_LOOP); -+ j(NOMATCH); -+ -+ bind(STR1_LOOP); -+ add(hlen_tmp, hlen_neg, 2 * haystack_chr_size); -+ add(ch2, haystack, hlen_tmp); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ bne(ch1, ch2, STR2_NEXT); -+ j(MATCH); -+ BLOCK_COMMENT("} string_indexof DO3"); -+ } -+ -+ if (needle_con_cnt == -1 || needle_con_cnt == 1) { -+ Label DO1_LOOP; -+ -+ BLOCK_COMMENT("string_indexof DO1 {"); -+ bind(DO1); -+ (this->*needle_load_1chr)(ch1, Address(needle), noreg); -+ sub(result_tmp, haystack_len, 1); -+ mv(tmp3, result_tmp); -+ if (haystack_chr_shift) { -+ slli(tmp3, result_tmp, haystack_chr_shift); -+ } -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(DO1_LOOP); -+ add(tmp3, haystack, hlen_neg); -+ (this->*haystack_load_1chr)(ch2, Address(tmp3), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, DO1_LOOP); -+ BLOCK_COMMENT("} string_indexof DO1"); -+ } -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ j(DONE); -+ -+ bind(MATCH); -+ srai(t0, hlen_neg, haystack_chr_shift); -+ add(result, result_tmp, t0); -+ -+ bind(DONE); -+} -+ -+// Compare strings. -+void C2_MacroAssembler::string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, -+ Register tmp3, int ae) -+{ -+ Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, -+ DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, -+ SHORT_LOOP_START, TAIL_CHECK, L; -+ -+ const int STUB_THRESHOLD = 64 + 8; -+ bool isLL = ae == StrIntrinsicNode::LL; -+ bool isLU = ae == StrIntrinsicNode::LU; -+ bool isUL = ae == StrIntrinsicNode::UL; -+ -+ bool str1_isL = isLL || isLU; -+ bool str2_isL = isLL || isUL; -+ -+ // for L strings, 1 byte for 1 character -+ // for U strings, 2 bytes for 1 character -+ int str1_chr_size = str1_isL ? 1 : 2; -+ int str2_chr_size = str2_isL ? 1 : 2; -+ int minCharsInWord = isLL ? wordSize : wordSize / 2; -+ -+ load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -+ -+ BLOCK_COMMENT("string_compare {"); -+ -+ // Bizzarely, the counts are passed in bytes, regardless of whether they -+ // are L or U strings, however the result is always in characters. -+ if (!str1_isL) { -+ sraiw(cnt1, cnt1, 1); -+ } -+ if (!str2_isL) { -+ sraiw(cnt2, cnt2, 1); -+ } -+ -+ // Compute the minimum of the string lengths and save the difference in result. -+ sub(result, cnt1, cnt2); -+ bgt(cnt1, cnt2, L); -+ mv(cnt2, cnt1); -+ bind(L); -+ -+ // A very short string -+ li(t0, minCharsInWord); -+ ble(cnt2, t0, SHORT_STRING); -+ -+ // Compare longwords -+ // load first parts of strings and finish initialization while loading -+ { -+ if (str1_isL == str2_isL) { // LL or UU -+ // load 8 bytes once to compare -+ ld(tmp1, Address(str1)); -+ beq(str1, str2, DONE); -+ ld(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ sub(cnt2, cnt2, minCharsInWord); -+ beqz(cnt2, TAIL_CHECK); -+ // convert cnt2 from characters to bytes -+ if (!str1_isL) { -+ slli(cnt2, cnt2, 1); -+ } -+ add(str2, str2, cnt2); -+ add(str1, str1, cnt2); -+ sub(cnt2, zr, cnt2); -+ } else if (isLU) { // LU case -+ lwu(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ addi(cnt2, cnt2, -4); -+ add(str1, str1, cnt2); -+ sub(cnt1, zr, cnt2); -+ slli(cnt2, cnt2, 1); -+ add(str2, str2, cnt2); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ sub(cnt2, zr, cnt2); -+ addi(cnt1, cnt1, 4); -+ } else { // UL case -+ ld(tmp1, Address(str1)); -+ lwu(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ addi(cnt2, cnt2, -4); -+ slli(t0, cnt2, 1); -+ sub(cnt1, zr, t0); -+ add(str1, str1, t0); -+ add(str2, str2, cnt2); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ sub(cnt2, zr, cnt2); -+ addi(cnt1, cnt1, 8); -+ } -+ addi(cnt2, cnt2, isUL ? 4 : 8); -+ bgez(cnt2, TAIL); -+ xorr(tmp3, tmp1, tmp2); -+ bnez(tmp3, DIFFERENCE); -+ -+ // main loop -+ bind(NEXT_WORD); -+ if (str1_isL == str2_isL) { // LL or UU -+ add(t0, str1, cnt2); -+ ld(tmp1, Address(t0)); -+ add(t0, str2, cnt2); -+ ld(tmp2, Address(t0)); -+ addi(cnt2, cnt2, 8); -+ } else if (isLU) { // LU case -+ add(t0, str1, cnt1); -+ lwu(tmp1, Address(t0)); -+ add(t0, str2, cnt2); -+ ld(tmp2, Address(t0)); -+ addi(cnt1, cnt1, 4); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ addi(cnt2, cnt2, 8); -+ } else { // UL case -+ add(t0, str2, cnt2); -+ lwu(tmp2, Address(t0)); -+ add(t0, str1, cnt1); -+ ld(tmp1, Address(t0)); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ addi(cnt1, cnt1, 8); -+ addi(cnt2, cnt2, 4); -+ } -+ bgez(cnt2, TAIL); -+ -+ xorr(tmp3, tmp1, tmp2); -+ beqz(tmp3, NEXT_WORD); -+ j(DIFFERENCE); -+ bind(TAIL); -+ xorr(tmp3, tmp1, tmp2); -+ bnez(tmp3, DIFFERENCE); -+ // Last longword. In the case where length == 4 we compare the -+ // same longword twice, but that's still faster than another -+ // conditional branch. -+ if (str1_isL == str2_isL) { // LL or UU -+ ld(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ } else if (isLU) { // LU case -+ lwu(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ } else { // UL case -+ lwu(tmp2, Address(str2)); -+ ld(tmp1, Address(str1)); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ } -+ bind(TAIL_CHECK); -+ xorr(tmp3, tmp1, tmp2); -+ beqz(tmp3, DONE); -+ -+ // Find the first different characters in the longwords and -+ // compute their difference. -+ bind(DIFFERENCE); -+ ctzc_bit(result, tmp3, isLL); // count zero from lsb to msb -+ srl(tmp1, tmp1, result); -+ srl(tmp2, tmp2, result); -+ if (isLL) { -+ andi(tmp1, tmp1, 0xFF); -+ andi(tmp2, tmp2, 0xFF); -+ } else { -+ andi(tmp1, tmp1, 0xFFFF); -+ andi(tmp2, tmp2, 0xFFFF); -+ } -+ sub(result, tmp1, tmp2); -+ j(DONE); -+ } -+ -+ bind(STUB); -+ RuntimeAddress stub = NULL; -+ switch (ae) { -+ case StrIntrinsicNode::LL: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LL()); -+ break; -+ case StrIntrinsicNode::UU: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UU()); -+ break; -+ case StrIntrinsicNode::LU: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LU()); -+ break; -+ case StrIntrinsicNode::UL: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UL()); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+ assert(stub.target() != NULL, "compare_long_string stub has not been generated"); -+ trampoline_call(stub); -+ j(DONE); -+ -+ bind(SHORT_STRING); -+ // Is the minimum length zero? -+ beqz(cnt2, DONE); -+ // arrange code to do most branches while loading and loading next characters -+ // while comparing previous -+ (this->*str1_load_chr)(tmp1, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST_INIT); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ j(SHORT_LOOP_START); -+ bind(SHORT_LOOP); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST); -+ bind(SHORT_LOOP_START); -+ (this->*str1_load_chr)(tmp2, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ (this->*str2_load_chr)(t0, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ bne(tmp1, cnt1, SHORT_LOOP_TAIL); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST2); -+ (this->*str1_load_chr)(tmp1, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ beq(tmp2, t0, SHORT_LOOP); -+ sub(result, tmp2, t0); -+ j(DONE); -+ bind(SHORT_LOOP_TAIL); -+ sub(result, tmp1, cnt1); -+ j(DONE); -+ bind(SHORT_LAST2); -+ beq(tmp2, t0, DONE); -+ sub(result, tmp2, t0); -+ -+ j(DONE); -+ bind(SHORT_LAST_INIT); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ bind(SHORT_LAST); -+ beq(tmp1, cnt1, DONE); -+ sub(result, tmp1, cnt1); -+ -+ bind(DONE); -+ -+ BLOCK_COMMENT("} string_compare"); -+} -+ -+void C2_MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, -+ Register tmp4, Register tmp5, Register tmp6, Register result, -+ Register cnt1, int elem_size) { -+ Label DONE, SAME, NEXT_DWORD, SHORT, TAIL, TAIL2, IS_TMP5_ZR; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ Register cnt2 = tmp2; // cnt2 only used in array length compare -+ Register elem_per_word = tmp6; -+ int log_elem_size = exact_log2(elem_size); -+ int length_offset = arrayOopDesc::length_offset_in_bytes(); -+ int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); -+ -+ assert(elem_size == 1 || elem_size == 2, "must be char or byte"); -+ assert_different_registers(a1, a2, result, cnt1, t0, t1, tmp3, tmp4, tmp5, tmp6); -+ li(elem_per_word, wordSize / elem_size); -+ -+ BLOCK_COMMENT("arrays_equals {"); -+ -+ // if (a1 == a2), return true -+ beq(a1, a2, SAME); -+ -+ mv(result, false); -+ beqz(a1, DONE); -+ beqz(a2, DONE); -+ lwu(cnt1, Address(a1, length_offset)); -+ lwu(cnt2, Address(a2, length_offset)); -+ bne(cnt2, cnt1, DONE); -+ beqz(cnt1, SAME); -+ -+ slli(tmp5, cnt1, 3 + log_elem_size); -+ sub(tmp5, zr, tmp5); -+ add(a1, a1, base_offset); -+ add(a2, a2, base_offset); -+ ld(tmp3, Address(a1, 0)); -+ ld(tmp4, Address(a2, 0)); -+ ble(cnt1, elem_per_word, SHORT); // short or same -+ -+ // Main 16 byte comparison loop with 2 exits -+ bind(NEXT_DWORD); { -+ ld(tmp1, Address(a1, wordSize)); -+ ld(tmp2, Address(a2, wordSize)); -+ sub(cnt1, cnt1, 2 * wordSize / elem_size); -+ blez(cnt1, TAIL); -+ bne(tmp3, tmp4, DONE); -+ ld(tmp3, Address(a1, 2 * wordSize)); -+ ld(tmp4, Address(a2, 2 * wordSize)); -+ add(a1, a1, 2 * wordSize); -+ add(a2, a2, 2 * wordSize); -+ ble(cnt1, elem_per_word, TAIL2); -+ } beq(tmp1, tmp2, NEXT_DWORD); -+ j(DONE); -+ -+ bind(TAIL); -+ xorr(tmp4, tmp3, tmp4); -+ xorr(tmp2, tmp1, tmp2); -+ sll(tmp2, tmp2, tmp5); -+ orr(tmp5, tmp4, tmp2); -+ j(IS_TMP5_ZR); -+ -+ bind(TAIL2); -+ bne(tmp1, tmp2, DONE); -+ -+ bind(SHORT); -+ xorr(tmp4, tmp3, tmp4); -+ sll(tmp5, tmp4, tmp5); -+ -+ bind(IS_TMP5_ZR); -+ bnez(tmp5, DONE); -+ -+ bind(SAME); -+ mv(result, true); -+ // That's it. -+ bind(DONE); -+ -+ BLOCK_COMMENT("} array_equals"); -+} -+ -+// Compare Strings -+ -+// For Strings we're passed the address of the first characters in a1 -+// and a2 and the length in cnt1. -+// elem_size is the element size in bytes: either 1 or 2. -+// There are two implementations. For arrays >= 8 bytes, all -+// comparisons (including the final one, which may overlap) are -+// performed 8 bytes at a time. For strings < 8 bytes, we compare a -+// halfword, then a short, and then a byte. -+ -+void C2_MacroAssembler::string_equals(Register a1, Register a2, -+ Register result, Register cnt1, int elem_size) -+{ -+ Label SAME, DONE, SHORT, NEXT_WORD; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ -+ assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte"); -+ assert_different_registers(a1, a2, result, cnt1, t0, t1); -+ -+ BLOCK_COMMENT("string_equals {"); -+ -+ mv(result, false); -+ -+ // Check for short strings, i.e. smaller than wordSize. -+ sub(cnt1, cnt1, wordSize); -+ bltz(cnt1, SHORT); -+ -+ // Main 8 byte comparison loop. -+ bind(NEXT_WORD); { -+ ld(tmp1, Address(a1, 0)); -+ add(a1, a1, wordSize); -+ ld(tmp2, Address(a2, 0)); -+ add(a2, a2, wordSize); -+ sub(cnt1, cnt1, wordSize); -+ bne(tmp1, tmp2, DONE); -+ } bgtz(cnt1, NEXT_WORD); -+ -+ // Last longword. In the case where length == 4 we compare the -+ // same longword twice, but that's still faster than another -+ // conditional branch. -+ // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when -+ // length == 4. -+ add(tmp1, a1, cnt1); -+ ld(tmp1, Address(tmp1, 0)); -+ add(tmp2, a2, cnt1); -+ ld(tmp2, Address(tmp2, 0)); -+ bne(tmp1, tmp2, DONE); -+ j(SAME); -+ -+ bind(SHORT); -+ Label TAIL03, TAIL01; -+ -+ // 0-7 bytes left. -+ andi(t0, cnt1, 4); -+ beqz(t0, TAIL03); -+ { -+ lwu(tmp1, Address(a1, 0)); -+ add(a1, a1, 4); -+ lwu(tmp2, Address(a2, 0)); -+ add(a2, a2, 4); -+ bne(tmp1, tmp2, DONE); -+ } -+ -+ bind(TAIL03); -+ // 0-3 bytes left. -+ andi(t0, cnt1, 2); -+ beqz(t0, TAIL01); -+ { -+ lhu(tmp1, Address(a1, 0)); -+ add(a1, a1, 2); -+ lhu(tmp2, Address(a2, 0)); -+ add(a2, a2, 2); -+ bne(tmp1, tmp2, DONE); -+ } -+ -+ bind(TAIL01); -+ if (elem_size == 1) { // Only needed when comparing 1-byte elements -+ // 0-1 bytes left. -+ andi(t0, cnt1, 1); -+ beqz(t0, SAME); -+ { -+ lbu(tmp1, a1, 0); -+ lbu(tmp2, a2, 0); -+ bne(tmp1, tmp2, DONE); -+ } -+ } -+ -+ // Arrays are equal. -+ bind(SAME); -+ mv(result, true); -+ -+ // That's it. -+ bind(DONE); -+ BLOCK_COMMENT("} string_equals"); -+} -+ -+typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far); -+typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label, -+ bool is_far, bool is_unordered); -+ -+static conditional_branch_insn conditional_branches[] = -+{ -+ /* SHORT branches */ -+ (conditional_branch_insn)&Assembler::beq, -+ (conditional_branch_insn)&Assembler::bgt, -+ NULL, // BoolTest::overflow -+ (conditional_branch_insn)&Assembler::blt, -+ (conditional_branch_insn)&Assembler::bne, -+ (conditional_branch_insn)&Assembler::ble, -+ NULL, // BoolTest::no_overflow -+ (conditional_branch_insn)&Assembler::bge, -+ -+ /* UNSIGNED branches */ -+ (conditional_branch_insn)&Assembler::beq, -+ (conditional_branch_insn)&Assembler::bgtu, -+ NULL, -+ (conditional_branch_insn)&Assembler::bltu, -+ (conditional_branch_insn)&Assembler::bne, -+ (conditional_branch_insn)&Assembler::bleu, -+ NULL, -+ (conditional_branch_insn)&Assembler::bgeu -+}; -+ -+static float_conditional_branch_insn float_conditional_branches[] = -+{ -+ /* FLOAT SHORT branches */ -+ (float_conditional_branch_insn)&MacroAssembler::float_beq, -+ (float_conditional_branch_insn)&MacroAssembler::float_bgt, -+ NULL, // BoolTest::overflow -+ (float_conditional_branch_insn)&MacroAssembler::float_blt, -+ (float_conditional_branch_insn)&MacroAssembler::float_bne, -+ (float_conditional_branch_insn)&MacroAssembler::float_ble, -+ NULL, // BoolTest::no_overflow -+ (float_conditional_branch_insn)&MacroAssembler::float_bge, -+ -+ /* DOUBLE SHORT branches */ -+ (float_conditional_branch_insn)&MacroAssembler::double_beq, -+ (float_conditional_branch_insn)&MacroAssembler::double_bgt, -+ NULL, -+ (float_conditional_branch_insn)&MacroAssembler::double_blt, -+ (float_conditional_branch_insn)&MacroAssembler::double_bne, -+ (float_conditional_branch_insn)&MacroAssembler::double_ble, -+ NULL, -+ (float_conditional_branch_insn)&MacroAssembler::double_bge -+}; -+ -+void C2_MacroAssembler::cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, bool is_far) { -+ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(conditional_branches) / sizeof(conditional_branches[0])), -+ "invalid conditional branch index"); -+ (this->*conditional_branches[cmpFlag])(op1, op2, label, is_far); -+} -+ -+// This is a function should only be used by C2. Flip the unordered when unordered-greater, C2 would use -+// unordered-lesser instead of unordered-greater. Finally, commute the result bits at function do_one_bytecode(). -+void C2_MacroAssembler::float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, bool is_far) { -+ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(float_conditional_branches) / sizeof(float_conditional_branches[0])), -+ "invalid float conditional branch index"); -+ int booltest_flag = cmpFlag & ~(C2_MacroAssembler::double_branch_mask); -+ (this->*float_conditional_branches[cmpFlag])(op1, op2, label, is_far, -+ (booltest_flag == (BoolTest::ge) || booltest_flag == (BoolTest::gt)) ? false : true); -+} -+ -+void C2_MacroAssembler::enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -+ switch (cmpFlag) { -+ case BoolTest::eq: -+ case BoolTest::le: -+ beqz(op1, L, is_far); -+ break; -+ case BoolTest::ne: -+ case BoolTest::gt: -+ bnez(op1, L, is_far); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+} -+ -+void C2_MacroAssembler::enc_cmpEqNe_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -+ switch (cmpFlag) { -+ case BoolTest::eq: -+ beqz(op1, L, is_far); -+ break; -+ case BoolTest::ne: -+ bnez(op1, L, is_far); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+} -+ -+void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Register dst, Register src) { -+ Label L; -+ cmp_branch(cmpFlag ^ (1 << neg_cond_bits), op1, op2, L); -+ mv(dst, src); -+ bind(L); -+} -+ -+// Set dst to NaN if any NaN input. -+void C2_MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRegister src2, -+ bool is_double, bool is_min) { -+ assert_different_registers(dst, src1, src2); -+ -+ Label Done; -+ fsflags(zr); -+ if (is_double) { -+ is_min ? fmin_d(dst, src1, src2) -+ : fmax_d(dst, src1, src2); -+ // Checking NaNs -+ flt_d(zr, src1, src2); -+ } else { -+ is_min ? fmin_s(dst, src1, src2) -+ : fmax_s(dst, src1, src2); -+ // Checking NaNs -+ flt_s(zr, src1, src2); -+ } -+ -+ frflags(t0); -+ beqz(t0, Done); -+ -+ // In case of NaNs -+ is_double ? fadd_d(dst, src1, src2) -+ : fadd_s(dst, src1, src2); -+ -+ bind(Done); -+} -+ -+void C2_MacroAssembler::element_compare(Register a1, Register a2, Register result, Register cnt, Register tmp1, Register tmp2, -+ VectorRegister vr1, VectorRegister vr2, VectorRegister vrs, bool islatin, Label &DONE) { -+ Label loop; -+ Assembler::SEW sew = islatin ? Assembler::e8 : Assembler::e16; -+ -+ bind(loop); -+ vsetvli(tmp1, cnt, sew, Assembler::m2); -+ vlex_v(vr1, a1, sew); -+ vlex_v(vr2, a2, sew); -+ vmsne_vv(vrs, vr1, vr2); -+ vfirst_m(tmp2, vrs); -+ bgez(tmp2, DONE); -+ sub(cnt, cnt, tmp1); -+ if (!islatin) { -+ slli(tmp1, tmp1, 1); // get byte counts -+ } -+ add(a1, a1, tmp1); -+ add(a2, a2, tmp1); -+ bnez(cnt, loop); -+ -+ mv(result, true); -+} -+ -+void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register result, Register cnt, int elem_size) { -+ Label DONE; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ -+ BLOCK_COMMENT("string_equals_v {"); -+ -+ mv(result, false); -+ -+ if (elem_size == 2) { -+ srli(cnt, cnt, 1); -+ } -+ -+ element_compare(a1, a2, result, cnt, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} string_equals_v"); -+} -+ -+// used by C2 ClearArray patterns. -+// base: Address of a buffer to be zeroed -+// cnt: Count in HeapWords -+// -+// base, cnt, v0, v1 and t0 are clobbered. -+void C2_MacroAssembler::clear_array_v(Register base, Register cnt) { -+ Label loop; -+ -+ // making zero words -+ vsetvli(t0, cnt, Assembler::e64, Assembler::m4); -+ vxor_vv(v0, v0, v0); -+ -+ bind(loop); -+ vsetvli(t0, cnt, Assembler::e64, Assembler::m4); -+ vse64_v(v0, base); -+ sub(cnt, cnt, t0); -+ shadd(base, t0, base, t0, 3); -+ bnez(cnt, loop); -+} -+ -+void C2_MacroAssembler::arrays_equals_v(Register a1, Register a2, Register result, -+ Register cnt1, int elem_size) { -+ Label DONE; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ Register cnt2 = tmp2; -+ int length_offset = arrayOopDesc::length_offset_in_bytes(); -+ int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); -+ -+ BLOCK_COMMENT("arrays_equals_v {"); -+ -+ // if (a1 == a2), return true -+ mv(result, true); -+ beq(a1, a2, DONE); -+ -+ mv(result, false); -+ // if a1 == null or a2 == null, return false -+ beqz(a1, DONE); -+ beqz(a2, DONE); -+ // if (a1.length != a2.length), return false -+ lwu(cnt1, Address(a1, length_offset)); -+ lwu(cnt2, Address(a2, length_offset)); -+ bne(cnt1, cnt2, DONE); -+ -+ la(a1, Address(a1, base_offset)); -+ la(a2, Address(a2, base_offset)); -+ -+ element_compare(a1, a2, result, cnt1, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); -+ -+ bind(DONE); -+ -+ BLOCK_COMMENT("} arrays_equals_v"); -+} -+ -+void C2_MacroAssembler::string_compare_v(Register str1, Register str2, Register cnt1, Register cnt2, -+ Register result, Register tmp1, Register tmp2, int encForm) { -+ Label DIFFERENCE, DONE, L, loop; -+ bool encLL = encForm == StrIntrinsicNode::LL; -+ bool encLU = encForm == StrIntrinsicNode::LU; -+ bool encUL = encForm == StrIntrinsicNode::UL; -+ -+ bool str1_isL = encLL || encLU; -+ bool str2_isL = encLL || encUL; -+ -+ int minCharsInWord = encLL ? wordSize : wordSize / 2; -+ -+ BLOCK_COMMENT("string_compare {"); -+ -+ // for Lating strings, 1 byte for 1 character -+ // for UTF16 strings, 2 bytes for 1 character -+ if (!str1_isL) -+ sraiw(cnt1, cnt1, 1); -+ if (!str2_isL) -+ sraiw(cnt2, cnt2, 1); -+ -+ // if str1 == str2, return the difference -+ // save the minimum of the string lengths in cnt2. -+ sub(result, cnt1, cnt2); -+ bgt(cnt1, cnt2, L); -+ mv(cnt2, cnt1); -+ bind(L); -+ -+ if (str1_isL == str2_isL) { // LL or UU -+ element_compare(str1, str2, zr, cnt2, tmp1, tmp2, v2, v4, v1, encLL, DIFFERENCE); -+ j(DONE); -+ } else { // LU or UL -+ Register strL = encLU ? str1 : str2; -+ Register strU = encLU ? str2 : str1; -+ VectorRegister vstr1 = encLU ? v4 : v0; -+ VectorRegister vstr2 = encLU ? v0 : v4; -+ -+ bind(loop); -+ vsetvli(tmp1, cnt2, Assembler::e8, Assembler::m2); -+ vle8_v(vstr1, strL); -+ vsetvli(tmp1, cnt2, Assembler::e16, Assembler::m4); -+ vzext_vf2(vstr2, vstr1); -+ vle16_v(vstr1, strU); -+ vmsne_vv(v0, vstr2, vstr1); -+ vfirst_m(tmp2, v0); -+ bgez(tmp2, DIFFERENCE); -+ sub(cnt2, cnt2, tmp1); -+ add(strL, strL, tmp1); -+ shadd(strU, tmp1, strU, tmp1, 1); -+ bnez(cnt2, loop); -+ j(DONE); -+ } -+ bind(DIFFERENCE); -+ slli(tmp1, tmp2, 1); -+ add(str1, str1, str1_isL ? tmp2 : tmp1); -+ add(str2, str2, str2_isL ? tmp2 : tmp1); -+ str1_isL ? lbu(tmp1, Address(str1, 0)) : lhu(tmp1, Address(str1, 0)); -+ str2_isL ? lbu(tmp2, Address(str2, 0)) : lhu(tmp2, Address(str2, 0)); -+ sub(result, tmp1, tmp2); -+ -+ bind(DONE); -+} -+ -+void C2_MacroAssembler::byte_array_inflate_v(Register src, Register dst, Register len, Register tmp) { -+ Label loop; -+ assert_different_registers(src, dst, len, tmp, t0); -+ -+ BLOCK_COMMENT("byte_array_inflate_v {"); -+ bind(loop); -+ vsetvli(tmp, len, Assembler::e8, Assembler::m2); -+ vle8_v(v2, src); -+ vsetvli(t0, len, Assembler::e16, Assembler::m4); -+ vzext_vf2(v0, v2); -+ vse16_v(v0, dst); -+ sub(len, len, tmp); -+ add(src, src, tmp); -+ shadd(dst, tmp, dst, tmp, 1); -+ bnez(len, loop); -+ BLOCK_COMMENT("} byte_array_inflate_v"); -+} -+ -+// Compress char[] array to byte[]. -+// result: the array length if every element in array can be encoded; 0, otherwise. -+void C2_MacroAssembler::char_array_compress_v(Register src, Register dst, Register len, Register result, Register tmp) { -+ Label done; -+ encode_iso_array_v(src, dst, len, result, tmp); -+ beqz(len, done); -+ mv(result, zr); -+ bind(done); -+} -+ -+// result: the number of elements had been encoded. -+void C2_MacroAssembler::encode_iso_array_v(Register src, Register dst, Register len, Register result, Register tmp) { -+ Label loop, DIFFERENCE, DONE; -+ -+ BLOCK_COMMENT("encode_iso_array_v {"); -+ mv(result, 0); -+ -+ bind(loop); -+ mv(tmp, 0xff); -+ vsetvli(t0, len, Assembler::e16, Assembler::m2); -+ vle16_v(v2, src); -+ // if element > 0xff, stop -+ vmsgtu_vx(v1, v2, tmp); -+ vfirst_m(tmp, v1); -+ vmsbf_m(v0, v1); -+ // compress char to byte -+ vsetvli(t0, len, Assembler::e8); -+ vncvt_x_x_w(v1, v2, Assembler::v0_t); -+ vse8_v(v1, dst, Assembler::v0_t); -+ -+ bgez(tmp, DIFFERENCE); -+ add(result, result, t0); -+ add(dst, dst, t0); -+ sub(len, len, t0); -+ shadd(src, t0, src, t0, 1); -+ bnez(len, loop); -+ j(DONE); -+ -+ bind(DIFFERENCE); -+ add(result, result, tmp); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} encode_iso_array_v"); -+} -+ -+void C2_MacroAssembler::count_positives_v(Register ary, Register len, Register result, Register tmp) { -+ Label LOOP, SET_RESULT, DONE; -+ -+ BLOCK_COMMENT("count_positives_v {"); -+ mv(result, zr); -+ -+ bind(LOOP); -+ vsetvli(t0, len, Assembler::e8, Assembler::m4); -+ vle8_v(v0, ary); -+ vmslt_vx(v0, v0, zr); -+ vfirst_m(tmp, v0); -+ bgez(tmp, SET_RESULT); -+ // if tmp == -1, all bytes are positive -+ add(result, result, t0); -+ -+ sub(len, len, t0); -+ add(ary, ary, t0); -+ bnez(len, LOOP); -+ j(DONE); -+ -+ // add remaining positive bytes count -+ bind(SET_RESULT); -+ add(result, result, tmp); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} count_positives_v"); -+} -+ -+void C2_MacroAssembler::string_indexof_char_v(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ bool isL) { -+ mv(result, zr); -+ -+ Label loop, MATCH, DONE; -+ Assembler::SEW sew = isL ? Assembler::e8 : Assembler::e16; -+ bind(loop); -+ vsetvli(tmp1, cnt1, sew, Assembler::m4); -+ vlex_v(v0, str1, sew); -+ vmseq_vx(v0, v0, ch); -+ vfirst_m(tmp2, v0); -+ bgez(tmp2, MATCH); // if equal, return index -+ -+ add(result, result, tmp1); -+ sub(cnt1, cnt1, tmp1); -+ if (!isL) slli(tmp1, tmp1, 1); -+ add(str1, str1, tmp1); -+ bnez(cnt1, loop); -+ -+ mv(result, -1); -+ j(DONE); -+ -+ bind(MATCH); -+ add(result, result, tmp2); -+ -+ bind(DONE); -+} -+ -+// Set dst to NaN if any NaN input. -+void C2_MacroAssembler::minmax_FD_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, -+ bool is_double, bool is_min) { -+ assert_different_registers(dst, src1, src2); -+ -+ vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); -+ -+ is_min ? vfmin_vv(dst, src1, src2) -+ : vfmax_vv(dst, src1, src2); -+ -+ vmfne_vv(v0, src1, src1); -+ vfadd_vv(dst, src1, src1, Assembler::v0_t); -+ vmfne_vv(v0, src2, src2); -+ vfadd_vv(dst, src2, src2, Assembler::v0_t); -+} -+ -+// Set dst to NaN if any NaN input. -+void C2_MacroAssembler::reduce_minmax_FD_v(FloatRegister dst, -+ FloatRegister src1, VectorRegister src2, -+ VectorRegister tmp1, VectorRegister tmp2, -+ bool is_double, bool is_min) { -+ assert_different_registers(src2, tmp1, tmp2); -+ -+ Label L_done, L_NaN; -+ vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); -+ vfmv_s_f(tmp2, src1); -+ -+ is_min ? vfredmin_vs(tmp1, src2, tmp2) -+ : vfredmax_vs(tmp1, src2, tmp2); -+ -+ fsflags(zr); -+ // Checking NaNs -+ vmflt_vf(tmp2, src2, src1); -+ frflags(t0); -+ bnez(t0, L_NaN); -+ j(L_done); -+ -+ bind(L_NaN); -+ vfmv_s_f(tmp2, src1); -+ vfredsum_vs(tmp1, src2, tmp2); -+ -+ bind(L_done); -+ vfmv_f_s(dst, tmp1); -+} -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -new file mode 100644 -index 00000000000..c71df4c101b ---- /dev/null -+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -@@ -0,0 +1,193 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP -+#define CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP -+ -+// C2_MacroAssembler contains high-level macros for C2 -+ -+ private: -+ void element_compare(Register r1, Register r2, -+ Register result, Register cnt, -+ Register tmp1, Register tmp2, -+ VectorRegister vr1, VectorRegister vr2, -+ VectorRegister vrs, -+ bool is_latin, Label& DONE); -+ public: -+ -+ void string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, -+ Register tmp1, Register tmp2, Register tmp3, -+ int ae); -+ -+ void string_indexof_char_short(Register str1, Register cnt1, -+ Register ch, Register result, -+ bool isL); -+ -+ void string_indexof_char(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ bool isL); -+ -+ void string_indexof(Register str1, Register str2, -+ Register cnt1, Register cnt2, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, int ae); -+ -+ void string_indexof_linearscan(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ int needle_con_cnt, Register result, int ae); -+ -+ void arrays_equals(Register r1, Register r2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ void string_equals(Register r1, Register r2, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ // refer to conditional_branches and float_conditional_branches -+ static const int bool_test_bits = 3; -+ static const int neg_cond_bits = 2; -+ static const int unsigned_branch_mask = 1 << bool_test_bits; -+ static const int double_branch_mask = 1 << bool_test_bits; -+ -+ // cmp -+ void cmp_branch(int cmpFlag, -+ Register op1, Register op2, -+ Label& label, bool is_far = false); -+ -+ void float_cmp_branch(int cmpFlag, -+ FloatRegister op1, FloatRegister op2, -+ Label& label, bool is_far = false); -+ -+ void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, -+ Label& L, bool is_far = false); -+ -+ void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, -+ Label& L, bool is_far = false); -+ -+ void enc_cmove(int cmpFlag, -+ Register op1, Register op2, -+ Register dst, Register src); -+ -+ void spill(Register r, bool is64, int offset) { -+ is64 ? sd(r, Address(sp, offset)) -+ : sw(r, Address(sp, offset)); -+ } -+ -+ void spill(FloatRegister f, bool is64, int offset) { -+ is64 ? fsd(f, Address(sp, offset)) -+ : fsw(f, Address(sp, offset)); -+ } -+ -+ void spill(VectorRegister v, int offset) { -+ add(t0, sp, offset); -+ vs1r_v(v, t0); -+ } -+ -+ void unspill(Register r, bool is64, int offset) { -+ is64 ? ld(r, Address(sp, offset)) -+ : lw(r, Address(sp, offset)); -+ } -+ -+ void unspillu(Register r, bool is64, int offset) { -+ is64 ? ld(r, Address(sp, offset)) -+ : lwu(r, Address(sp, offset)); -+ } -+ -+ void unspill(FloatRegister f, bool is64, int offset) { -+ is64 ? fld(f, Address(sp, offset)) -+ : flw(f, Address(sp, offset)); -+ } -+ -+ void unspill(VectorRegister v, int offset) { -+ add(t0, sp, offset); -+ vl1r_v(v, t0); -+ } -+ -+ void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, int vec_reg_size_in_bytes) { -+ assert(vec_reg_size_in_bytes % 16 == 0, "unexpected vector reg size"); -+ unspill(v0, src_offset); -+ spill(v0, dst_offset); -+ } -+ -+ void minmax_FD(FloatRegister dst, -+ FloatRegister src1, FloatRegister src2, -+ bool is_double, bool is_min); -+ -+ // intrinsic methods implemented by rvv instructions -+ void string_equals_v(Register r1, Register r2, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ void arrays_equals_v(Register r1, Register r2, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ void string_compare_v(Register str1, Register str2, -+ Register cnt1, Register cnt2, -+ Register result, -+ Register tmp1, Register tmp2, -+ int encForm); -+ -+ void clear_array_v(Register base, Register cnt); -+ -+ void byte_array_inflate_v(Register src, Register dst, -+ Register len, Register tmp); -+ -+ void char_array_compress_v(Register src, Register dst, -+ Register len, Register result, -+ Register tmp); -+ -+ void encode_iso_array_v(Register src, Register dst, -+ Register len, Register result, -+ Register tmp); -+ -+ void count_positives_v(Register ary, Register len, -+ Register result, Register tmp); -+ -+ void string_indexof_char_v(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ bool isL); -+ -+ void minmax_FD_v(VectorRegister dst, -+ VectorRegister src1, VectorRegister src2, -+ bool is_double, bool is_min); -+ -+ void reduce_minmax_FD_v(FloatRegister dst, -+ FloatRegister src1, VectorRegister src2, -+ VectorRegister tmp1, VectorRegister tmp2, -+ bool is_double, bool is_min); -+ -+#endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp new file mode 100644 -index 00000000000..53a41665f4b +index 0000000000..3da1f1c6d8 --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -@@ -0,0 +1,83 @@ +@@ -0,0 +1,90 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -13580,19 +11614,23 @@ index 00000000000..53a41665f4b +// (see c2_globals.hpp). Alpha-sorted. + +define_pd_global(bool, BackgroundCompilation, true); ++define_pd_global(bool, UseTLAB, true); ++define_pd_global(bool, ResizeTLAB, true); +define_pd_global(bool, CICompileOSR, true); +define_pd_global(bool, InlineIntrinsics, true); +define_pd_global(bool, PreferInterpreterNativeStubs, false); +define_pd_global(bool, ProfileTraps, true); +define_pd_global(bool, UseOnStackReplacement, true); +define_pd_global(bool, ProfileInterpreter, true); -+define_pd_global(bool, TieredCompilation, COMPILER1_PRESENT(true) NOT_COMPILER1(false)); ++define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(intx, CompileThreshold, 10000); + +define_pd_global(intx, OnStackReplacePercentage, 140); +define_pd_global(intx, ConditionalMoveLimit, 0); ++define_pd_global(intx, FLOATPRESSURE, 32); +define_pd_global(intx, FreqInlineSize, 325); +define_pd_global(intx, MinJumpTableSize, 10); ++define_pd_global(intx, INTPRESSURE, 24); +define_pd_global(intx, InteriorEntryAlignment, 16); +define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); +define_pd_global(intx, LoopUnrollLimit, 60); @@ -13622,6 +11660,9 @@ index 00000000000..53a41665f4b +define_pd_global(uintx, CodeCacheMinBlockLength, 6); +define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); + ++// Heap related flags ++define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); ++ +// Ergonomics related flags +define_pd_global(bool, NeverActAsServerClassMachine, false); + @@ -13630,7 +11671,7 @@ index 00000000000..53a41665f4b +#endif // CPU_RISCV_C2_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/c2_init_riscv.cpp b/src/hotspot/cpu/riscv/c2_init_riscv.cpp new file mode 100644 -index 00000000000..cdbd69807be +index 0000000000..cdbd69807b --- /dev/null +++ b/src/hotspot/cpu/riscv/c2_init_riscv.cpp @@ -0,0 +1,38 @@ @@ -13672,62 +11713,9 @@ index 00000000000..cdbd69807be + guarantee(CodeEntryAlignment >= InteriorEntryAlignment, "" ); + reg_mask_init(); +} -diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp -new file mode 100644 -index 00000000000..a90d9fdc160 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp -@@ -0,0 +1,47 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "asm/macroAssembler.hpp" -+#include "opto/compile.hpp" -+#include "opto/node.hpp" -+#include "opto/output.hpp" -+#include "runtime/sharedRuntime.hpp" -+ -+#define __ masm. -+void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { -+ assert(SharedRuntime::polling_page_return_handler_blob() != NULL, -+ "polling page return stub not created yet"); -+ address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); -+ RuntimeAddress callback_addr(stub); -+ -+ __ bind(entry->_stub_label); -+ InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); -+ masm.code_section()->relocate(masm.pc(), safepoint_pc.rspec()); -+ __ la(t0, safepoint_pc.target()); -+ __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); -+ __ far_jump(callback_addr); -+} -+#undef __ diff --git a/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp new file mode 100644 -index 00000000000..14a68b45026 +index 0000000000..14a68b4502 --- /dev/null +++ b/src/hotspot/cpu/riscv/codeBuffer_riscv.hpp @@ -0,0 +1,36 @@ @@ -13769,7 +11757,7 @@ index 00000000000..14a68b45026 +#endif // CPU_RISCV_CODEBUFFER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp new file mode 100644 -index 00000000000..75bc4be7840 +index 0000000000..a4de342a93 --- /dev/null +++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp @@ -0,0 +1,149 @@ @@ -13844,8 +11832,8 @@ index 00000000000..75bc4be7840 +#undef __ + +int CompiledStaticCall::to_interp_stub_size() { -+ // fence_i + fence* + (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr -+ return NativeFenceI::instruction_size() + 12 * NativeInstruction::instruction_size; ++ // (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr ++ return 12 * NativeInstruction::instruction_size; +} + +int CompiledStaticCall::to_trampoline_stub_size() { @@ -13861,7 +11849,7 @@ index 00000000000..75bc4be7840 +} + +void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { -+ address stub = find_stub(); ++ address stub = find_stub(false /* is_aot */); + guarantee(stub != NULL, "stub not found"); + + if (TraceICs) { @@ -13872,12 +11860,16 @@ index 00000000000..75bc4be7840 + } + + // Creation also verifies the object. -+ NativeMovConstReg* method_holder -+ = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); -+#ifdef ASSERT ++ NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); ++#ifndef PRODUCT + NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); + -+ verify_mt_safe(callee, entry, method_holder, jump); ++ // read the value once ++ volatile intptr_t data = method_holder->data(); ++ assert(data == 0 || data == (intptr_t)callee(), ++ "a) MT-unsafe modification of inline cache"); ++ assert(data == 0 || jump->jump_destination() == entry, ++ "b) MT-unsafe modification of inline cache"); +#endif + // Update stub. + method_holder->set_data((intptr_t)callee()); @@ -13888,16 +11880,13 @@ index 00000000000..75bc4be7840 +} + +void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { ++ assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); + // Reset stub. + address stub = static_stub->addr(); + assert(stub != NULL, "stub not found"); -+ assert(CompiledICLocker::is_safe(stub), "mt unsafe call"); + // Creation also verifies the object. -+ NativeMovConstReg* method_holder -+ = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); ++ NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); + method_holder->set_data(0); -+ NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); -+ jump->set_jump_destination((address)-1); +} + +//----------------------------------------------------------------------------- @@ -13910,11 +11899,10 @@ index 00000000000..75bc4be7840 + _call->verify_alignment(); + + // Verify stub. -+ address stub = find_stub(); ++ address stub = find_stub(false /* is_aot */); + assert(stub != NULL, "no stub found for static call"); + // Creation also verifies the object. -+ NativeMovConstReg* method_holder -+ = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); ++ NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); + NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); + + // Verify state. @@ -13924,10 +11912,10 @@ index 00000000000..75bc4be7840 +#endif // !PRODUCT diff --git a/src/hotspot/cpu/riscv/copy_riscv.hpp b/src/hotspot/cpu/riscv/copy_riscv.hpp new file mode 100644 -index 00000000000..bceadcc5dcc +index 0000000000..05da242e35 --- /dev/null +++ b/src/hotspot/cpu/riscv/copy_riscv.hpp -@@ -0,0 +1,136 @@ +@@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -13957,7 +11945,10 @@ index 00000000000..bceadcc5dcc +#ifndef CPU_RISCV_COPY_RISCV_HPP +#define CPU_RISCV_COPY_RISCV_HPP + -+#include OS_CPU_HEADER(copy) ++// Inline functions for memory copy and fill. ++ ++// Contains inline asm implementations ++#include OS_CPU_HEADER_INLINE(copy) + +static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { + julong* to = (julong*) tohw; @@ -13983,93 +11974,51 @@ index 00000000000..bceadcc5dcc + (void)memset(to, 0, count); +} + -+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ (void)memmove(to, from, count * HeapWordSize); -+} -+ -+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ switch (count) { -+ case 8: to[7] = from[7]; // fall through -+ case 7: to[6] = from[6]; // fall through -+ case 6: to[5] = from[5]; // fall through -+ case 5: to[4] = from[4]; // fall through -+ case 4: to[3] = from[3]; // fall through -+ case 3: to[2] = from[2]; // fall through -+ case 2: to[1] = from[1]; // fall through -+ case 1: to[0] = from[0]; // fall through -+ case 0: break; -+ default: -+ memcpy(to, from, count * HeapWordSize); -+ break; -+ } -+} -+ -+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { -+ shared_disjoint_words_atomic(from, to, count); -+} -+ -+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ pd_conjoint_words(from, to, count); -+} -+ -+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ pd_disjoint_words(from, to, count); -+} -+ -+static void pd_conjoint_bytes(const void* from, void* to, size_t count) { -+ (void)memmove(to, from, count); -+} -+ -+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { -+ pd_conjoint_bytes(from, to, count); -+} -+ -+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { -+ _Copy_conjoint_jshorts_atomic(from, to, count); -+} -+ -+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { -+ _Copy_conjoint_jints_atomic(from, to, count); -+} -+ -+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { -+ _Copy_conjoint_jlongs_atomic(from, to, count); -+} -+ -+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { -+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size."); -+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -+} -+ -+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_bytes(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jshorts(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jints(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jlongs(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { -+ assert(!UseCompressedOops, "foo!"); -+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); -+ _Copy_arrayof_conjoint_jlongs(from, to, count); -+} -+ +#endif // CPU_RISCV_COPY_RISCV_HPP +diff --git a/src/hotspot/cpu/riscv/depChecker_riscv.hpp b/src/hotspot/cpu/riscv/depChecker_riscv.hpp +new file mode 100644 +index 0000000000..e9ff307b64 +--- /dev/null ++++ b/src/hotspot/cpu/riscv/depChecker_riscv.hpp +@@ -0,0 +1,32 @@ ++/* ++ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2014, Red Hat Inc. All rights reserved. ++ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ * ++ */ ++ ++#ifndef CPU_RISCV_VM_DEPCHECKER_RISCV_HPP ++#define CPU_RISCV_VM_DEPCHECKER_RISCV_HPP ++ ++// Nothing to do on riscv ++ ++#endif // CPU_RISCV_VM_DEPCHECKER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/disassembler_riscv.hpp b/src/hotspot/cpu/riscv/disassembler_riscv.hpp new file mode 100644 -index 00000000000..b0e5560c906 +index 0000000000..06bca5298c --- /dev/null +++ b/src/hotspot/cpu/riscv/disassembler_riscv.hpp -@@ -0,0 +1,58 @@ +@@ -0,0 +1,38 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -14107,121 +12056,13 @@ index 00000000000..b0e5560c906 + return ""; +} + -+// Returns address of n-th instruction preceding addr, -+// NULL if no preceding instruction can be found. -+// On riscv, we assume a constant instruction length. -+// It might be beneficial to check "is_readable" as we do on ppc and s390. -+static address find_prev_instr(address addr, int n_instr) { -+ return addr - Assembler::instruction_size * n_instr; -+} -+ -+// special-case instruction decoding. -+// There may be cases where the binutils disassembler doesn't do -+// the perfect job. In those cases, decode_instruction0 may kick in -+// and do it right. -+// If nothing had to be done, just return "here", otherwise return "here + instr_len(here)" -+static address decode_instruction0(address here, outputStream* st, address virtual_begin = NULL) { -+ return here; -+} -+ -+// platform-specific instruction annotations (like value of loaded constants) -+static void annotate(address pc, outputStream* st) {} -+ +#endif // CPU_RISCV_DISASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp b/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp -new file mode 100644 -index 00000000000..5c700be9c91 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp -@@ -0,0 +1,44 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "prims/foreign_globals.hpp" -+#include "utilities/debug.hpp" -+ -+// Stubbed out, implement later -+const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const { -+ Unimplemented(); -+ return {}; -+} -+ -+const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) const { -+ Unimplemented(); -+ return {}; -+} -+ -+const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const { -+ ShouldNotCallThis(); -+ return {}; -+} -diff --git a/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp b/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp -new file mode 100644 -index 00000000000..3ac89752c27 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP -+#define CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP -+ -+class ABIDescriptor {}; -+class BufferLayout {}; -+ -+#endif // CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp new file mode 100644 -index 00000000000..6e38960598a +index 0000000000..d4fcbdcbbd --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -0,0 +1,697 @@ +@@ -0,0 +1,694 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -14253,7 +12094,6 @@ index 00000000000..6e38960598a +#include "interpreter/interpreter.hpp" +#include "memory/resourceArea.hpp" +#include "memory/universe.hpp" -+#include "oops/markWord.hpp" +#include "oops/method.hpp" +#include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" @@ -14263,7 +12103,6 @@ index 00000000000..6e38960598a +#include "runtime/monitorChunk.hpp" +#include "runtime/os.inline.hpp" +#include "runtime/signature.hpp" -+#include "runtime/stackWatermarkSet.hpp" +#include "runtime/stubCodeGenerator.hpp" +#include "runtime/stubRoutines.hpp" +#include "vmreg_riscv.inline.hpp" @@ -14281,13 +12120,21 @@ index 00000000000..6e38960598a +// Profiling/safepoint support + +bool frame::safe_for_sender(JavaThread *thread) { -+ address addr_sp = (address)_sp; -+ address addr_fp = (address)_fp; ++ address sp = (address)_sp; ++ address fp = (address)_fp; + address unextended_sp = (address)_unextended_sp; + + // consider stack guards when trying to determine "safe" stack pointers ++ static size_t stack_guard_size = os::uses_stack_guard_pages() ? ++ (JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size()) : 0; ++ size_t usable_stack_size = thread->stack_size() - stack_guard_size; ++ + // sp must be within the usable part of the stack (not in guards) -+ if (!thread->is_in_usable_stack(addr_sp)) { ++ bool sp_safe = (sp < thread->stack_base()) && ++ (sp >= thread->stack_base() - usable_stack_size); ++ ++ ++ if (!sp_safe) { + return false; + } + @@ -14304,14 +12151,15 @@ index 00000000000..6e38960598a + // So unextended sp must be within the stack but we need not to check + // that unextended sp >= sp + -+ if (!thread->is_in_full_stack_checked(unextended_sp)) { ++ bool unextended_sp_safe = (unextended_sp < thread->stack_base()); ++ ++ if (!unextended_sp_safe) { + return false; + } + + // an fp must be within the stack and above (but not equal) sp + // second evaluation on fp+ is added to handle situation where fp is -1 -+ bool fp_safe = thread->is_in_stack_range_excl(addr_fp, addr_sp) && -+ thread->is_in_full_stack_checked(addr_fp + (return_addr_offset * sizeof(void*))); ++ bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); + + // We know sp/unextended_sp are safe only fp is questionable here + @@ -14372,7 +12220,7 @@ index 00000000000..6e38960598a + + sender_sp = _unextended_sp + _cb->frame_size(); + // Is sender_sp safe? -+ if (!thread->is_in_full_stack_checked((address)sender_sp)) { ++ if ((address)sender_sp >= thread->stack_base()) { + return false; + } + @@ -14388,7 +12236,10 @@ index 00000000000..6e38960598a + // fp is always saved in a recognizable place in any code we generate. However + // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved fp + // is really a frame pointer. -+ if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { ++ ++ bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); ++ ++ if (!saved_fp_safe) { + return false; + } + @@ -14421,7 +12272,9 @@ index 00000000000..6e38960598a + + // Could be the call_stub + if (StubRoutines::returns_to_call_stub(sender_pc)) { -+ if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { ++ bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); ++ ++ if (!saved_fp_safe) { + return false; + } + @@ -14481,7 +12334,6 @@ index 00000000000..6e38960598a +} + +void frame::patch_pc(Thread* thread, address pc) { -+ assert(_cb == CodeCache::find_blob(pc), "unexpected pc"); + address* pc_addr = &(((address*) sp())[-1]); + if (TracePcPatching) { + tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]", @@ -14491,6 +12343,7 @@ index 00000000000..6e38960598a + // patch in the same address that's already there. + assert(_pc == *pc_addr || pc == *pc_addr, "must be"); + *pc_addr = pc; ++ _cb = CodeCache::find_blob(pc); + address original_pc = CompiledMethod::get_deopt_original_pc(this); + if (original_pc != NULL) { + assert(original_pc == _pc, "expected original PC to be stored before patching"); @@ -14573,21 +12426,6 @@ index 00000000000..6e38960598a + return fr; +} + -+OptimizedEntryBlob::FrameData* OptimizedEntryBlob::frame_data_for_frame(const frame& frame) const { -+ ShouldNotCallThis(); -+ return nullptr; -+} -+ -+bool frame::optimized_entry_frame_is_first() const { -+ ShouldNotCallThis(); -+ return false; -+} -+ -+frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const { -+ ShouldNotCallThis(); -+ return {}; -+} -+ +//------------------------------------------------------------------------------ +// frame::verify_deopt_original_pc +// @@ -14706,8 +12544,8 @@ index 00000000000..6e38960598a +} + +//------------------------------------------------------------------------------ -+// frame::sender_raw -+frame frame::sender_raw(RegisterMap* map) const { ++// frame::sender ++frame frame::sender(RegisterMap* map) const { + // Default is we done have to follow them. The sender_for_xxx will + // update it accordingly + assert(map != NULL, "map must be set"); @@ -14732,16 +12570,6 @@ index 00000000000..6e38960598a + return frame(sender_sp(), link(), sender_pc()); +} + -+frame frame::sender(RegisterMap* map) const { -+ frame result = sender_raw(map); -+ -+ if (map->process_frames()) { -+ StackWatermarkSet::on_iteration(map->thread(), result); -+ } -+ -+ return result; -+} -+ +bool frame::is_interpreted_frame_valid(JavaThread* thread) const { + assert(is_interpreted_frame(), "Not an interpreted frame"); + // These are reasonable sanity checks @@ -14792,7 +12620,16 @@ index 00000000000..6e38960598a + + // validate locals + address locals = (address) *interpreter_frame_locals_addr(); -+ if (locals > thread->stack_base() || locals < (address) fp()) { ++ if (locals > thread->stack_base()) { ++ return false; ++ } ++ ++ if (m->max_locals() > 0 && locals < (address) fp()) { ++ // fp in interpreter frame on RISC-V is higher than that on AArch64, ++ // pointing to sender_sp and sender_sp-2 relatively. ++ // On RISC-V, if max_locals is 0, the 'locals' pointer may be below fp, ++ // pointing to sender_sp-1 (with one padding slot). ++ // So we verify the 'locals' pointer only if max_locals > 0. + return false; + } + @@ -14826,7 +12663,7 @@ index 00000000000..6e38960598a + oop* obj_p = (oop*)tos_addr; + obj = (obj_p == NULL) ? (oop)NULL : *obj_p; + } -+ assert(Universe::is_in_heap_or_null(obj), "sanity check"); ++ assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + *oop_result = obj; + break; + } @@ -14900,6 +12737,7 @@ index 00000000000..6e38960598a + init((intptr_t*)ptr_sp, (intptr_t*)ptr_fp, (address)pc); +} + ++void frame::pd_ps() {} +#endif + +void JavaFrameAnchor::make_walkable(JavaThread* thread) { @@ -14921,10 +12759,10 @@ index 00000000000..6e38960598a +} diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp new file mode 100644 -index 00000000000..c06aaa9e391 +index 0000000000..18e021dcb9 --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.hpp -@@ -0,0 +1,202 @@ +@@ -0,0 +1,199 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -15058,7 +12896,7 @@ index 00000000000..c06aaa9e391 + // Entry frames + // n.b. these values are determined by the layout defined in + // stubGenerator for the Java call stub -+ entry_frame_after_call_words = 22, ++ entry_frame_after_call_words = 34, + entry_frame_call_wrapper_offset = -10, + + // we don't need a save area @@ -15123,16 +12961,13 @@ index 00000000000..c06aaa9e391 + + static jint interpreter_frame_expression_stack_direction() { return -1; } + -+ // returns the sending frame, without applying any barriers -+ frame sender_raw(RegisterMap* map) const; -+ +#endif // CPU_RISCV_FRAME_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp new file mode 100644 -index 00000000000..5ac1bf57f57 +index 0000000000..abd5bda7e4 --- /dev/null +++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp -@@ -0,0 +1,248 @@ +@@ -0,0 +1,245 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -15365,8 +13200,6 @@ index 00000000000..5ac1bf57f57 + + +// Compiled frames -+PRAGMA_DIAG_PUSH -+PRAGMA_NONNULL_IGNORED +inline oop frame::saved_oop_result(RegisterMap* map) const { + oop* result_adr = (oop *)map->location(x10->as_VMReg()); + guarantee(result_adr != NULL, "bad register save location"); @@ -15378,18 +13211,17 @@ index 00000000000..5ac1bf57f57 + guarantee(result_adr != NULL, "bad register save location"); + *result_adr = obj; +} -+PRAGMA_DIAG_POP + +#endif // CPU_RISCV_FRAME_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp new file mode 100644 -index 00000000000..1c46b3947d3 +index 0000000000..c5ccf040c7 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -0,0 +1,484 @@ +@@ -0,0 +1,475 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. ++ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -15434,7 +13266,6 @@ index 00000000000..1c46b3947d3 + +void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register addr, Register count, RegSet saved_regs) { -+ assert_cond(masm != NULL); + bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0; + if (!dest_uninitialized) { + Label done; @@ -15477,7 +13308,6 @@ index 00000000000..1c46b3947d3 + +void G1BarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs) { -+ assert_cond(masm != NULL); + __ push_reg(saved_regs, sp); + assert_different_registers(start, count, tmp); + assert_different_registers(c_rarg0, count); @@ -15498,7 +13328,6 @@ index 00000000000..1c46b3947d3 + // directly to skip generating the check by + // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp. + -+ assert_cond(masm != NULL); + assert(thread == xthread, "must be"); + + Label done; @@ -15546,21 +13375,15 @@ index 00000000000..1c46b3947d3 + __ j(done); + + __ bind(runtime); -+ // save the live input values -+ RegSet saved = RegSet::of(pre_val); -+ if (tosca_live) { saved += RegSet::of(x10); } -+ if (obj != noreg) { saved += RegSet::of(obj); } -+ -+ __ push_reg(saved, sp); + ++ __ push_call_clobbered_registers(); + if (expand_call) { + assert(pre_val != c_rarg1, "smashed arg"); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); + } else { + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); + } -+ -+ __ pop_reg(saved, sp); ++ __ pop_call_clobbered_registers(); + + __ bind(done); + @@ -15572,7 +13395,6 @@ index 00000000000..1c46b3947d3 + Register thread, + Register tmp, + Register tmp2) { -+ assert_cond(masm != NULL); + assert(thread == xthread, "must be"); + assert_different_registers(store_addr, new_val, thread, tmp, tmp2, + t0); @@ -15585,6 +13407,7 @@ index 00000000000..1c46b3947d3 + BarrierSet* bs = BarrierSet::barrier_set(); + CardTableBarrierSet* ctbs = barrier_set_cast(bs); + CardTable* ct = ctbs->card_table(); ++ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); + + Label done; + Label runtime; @@ -15602,9 +13425,10 @@ index 00000000000..1c46b3947d3 + // storing region crossing non-NULL, is card already dirty? + + ExternalAddress cardtable((address) ct->byte_map_base()); ++ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); + const Register card_addr = tmp; + -+ __ srli(card_addr, store_addr, CardTable::card_shift()); ++ __ srli(card_addr, store_addr, CardTable::card_shift); + + // get the address of the card + __ load_byte_map_base(tmp2); @@ -15637,7 +13461,7 @@ index 00000000000..1c46b3947d3 + + __ bind(runtime); + // save the live input values -+ RegSet saved = RegSet::of(store_addr); ++ RegSet saved = RegSet::of(store_addr, new_val); + __ push_reg(saved, sp); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); + __ pop_reg(saved, sp); @@ -15647,7 +13471,6 @@ index 00000000000..1c46b3947d3 + +void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { -+ assert_cond(masm != NULL); + bool on_oop = is_reference_type(type); + bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0; + bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0; @@ -15671,7 +13494,6 @@ index 00000000000..1c46b3947d3 + +void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { -+ assert_cond(masm != NULL); + // flatten object address if needed + if (dst.offset() == 0) { + if (dst.base() != x13) { @@ -15727,7 +13549,7 @@ index 00000000000..1c46b3947d3 + Register pre_val_reg = stub->pre_val()->as_register(); + + if (stub->do_load()) { -+ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); ++ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */, false /*unaligned*/); + } + __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); + ce->store_parameter(stub->pre_val()->as_register(), 0); @@ -15808,6 +13630,7 @@ index 00000000000..1c46b3947d3 + BarrierSet* bs = BarrierSet::barrier_set(); + CardTableBarrierSet* ctbs = barrier_set_cast(bs); + CardTable* ct = ctbs->card_table(); ++ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); + + Label done; + Label runtime; @@ -15826,7 +13649,7 @@ index 00000000000..1c46b3947d3 + assert_different_registers(card_offset, byte_map_base, t0); + + __ load_parameter(0, card_offset); -+ __ srli(card_offset, card_offset, CardTable::card_shift()); ++ __ srli(card_offset, card_offset, CardTable::card_shift); + __ load_byte_map_base(byte_map_base); + + // Convert card offset into an address in card_addr @@ -15873,7 +13696,7 @@ index 00000000000..1c46b3947d3 +#endif // COMPILER1 diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp new file mode 100644 -index 00000000000..37bc183f39c +index 0000000000..37bc183f39 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.hpp @@ -0,0 +1,78 @@ @@ -15957,7 +13780,7 @@ index 00000000000..37bc183f39c +#endif // CPU_RISCV_GC_G1_G1BARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp b/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp new file mode 100644 -index 00000000000..8735fd014ff +index 0000000000..8735fd014f --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1Globals_riscv.hpp @@ -0,0 +1,31 @@ @@ -15994,10 +13817,10 @@ index 00000000000..8735fd014ff +#endif // CPU_RISCV_GC_G1_G1GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp new file mode 100644 -index 00000000000..3c115a2ea02 +index 0000000000..2b439280fa --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp -@@ -0,0 +1,302 @@ +@@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -16027,7 +13850,6 @@ index 00000000000..3c115a2ea02 +#include "classfile/classLoaderData.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/barrierSetAssembler.hpp" -+#include "gc/shared/barrierSetNMethod.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interp_masm.hpp" +#include "memory/universe.hpp" @@ -16040,8 +13862,6 @@ index 00000000000..3c115a2ea02 + +void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Register dst, Address src, Register tmp1, Register tmp_thread) { -+ assert_cond(masm != NULL); -+ + // RA is live. It must be saved around calls. + + bool in_heap = (decorators & IN_HEAP) != 0; @@ -16082,7 +13902,6 @@ index 00000000000..3c115a2ea02 + +void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { -+ assert_cond(masm != NULL); + bool in_heap = (decorators & IN_HEAP) != 0; + bool in_native = (decorators & IN_NATIVE) != 0; + switch (type) { @@ -16124,7 +13943,6 @@ index 00000000000..3c115a2ea02 + +void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath) { -+ assert_cond(masm != NULL); + // If mask changes we need to ensure that the inverse is still encodable as an immediate + STATIC_ASSERT(JNIHandles::weak_tag_mask == 1); + __ andi(obj, obj, ~JNIHandles::weak_tag_mask); @@ -16139,7 +13957,6 @@ index 00000000000..3c115a2ea02 + Register tmp2, + Label& slow_case, + bool is_far) { -+ assert_cond(masm != NULL); + assert_different_registers(obj, tmp2); + assert_different_registers(obj, var_size_in_bytes); + Register end = tmp2; @@ -16219,7 +14036,6 @@ index 00000000000..3c115a2ea02 + Register var_size_in_bytes, + int con_size_in_bytes, + Register tmp1) { -+ assert_cond(masm != NULL); + assert(tmp1->is_valid(), "need temp reg"); + + __ ld(tmp1, Address(xthread, in_bytes(JavaThread::allocated_bytes_offset()))); @@ -16230,82 +14046,12 @@ index 00000000000..3c115a2ea02 + } + __ sd(tmp1, Address(xthread, in_bytes(JavaThread::allocated_bytes_offset()))); +} -+ -+void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { -+ BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); -+ -+ if (bs_nm == NULL) { -+ return; -+ } -+ -+ // RISCV atomic operations require that the memory address be naturally aligned. -+ __ align(4); -+ -+ Label skip, guard; -+ Address thread_disarmed_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset())); -+ -+ __ lwu(t0, guard); -+ -+ // Subsequent loads of oops must occur after load of guard value. -+ // BarrierSetNMethod::disarm sets guard with release semantics. -+ __ membar(MacroAssembler::LoadLoad); -+ __ lwu(t1, thread_disarmed_addr); -+ __ beq(t0, t1, skip); -+ -+ int32_t offset = 0; -+ __ movptr_with_offset(t0, StubRoutines::riscv::method_entry_barrier(), offset); -+ __ jalr(ra, t0, offset); -+ __ j(skip); -+ -+ __ bind(guard); -+ -+ assert(__ offset() % 4 == 0, "bad alignment"); -+ __ emit_int32(0); // nmethod guard value. Skipped over in common case. -+ -+ __ bind(skip); -+} -+ -+void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { -+ BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod(); -+ if (bs == NULL) { -+ return; -+ } -+ -+ Label bad_call; -+ __ beqz(xmethod, bad_call); -+ -+ // Pointer chase to the method holder to find out if the method is concurrently unloading. -+ Label method_live; -+ __ load_method_holder_cld(t0, xmethod); -+ -+ // Is it a strong CLD? -+ __ lwu(t1, Address(t0, ClassLoaderData::keep_alive_offset())); -+ __ bnez(t1, method_live); -+ -+ // Is it a weak but alive CLD? -+ __ push_reg(RegSet::of(x28, x29), sp); -+ -+ __ ld(x28, Address(t0, ClassLoaderData::holder_offset())); -+ -+ // Uses x28 & x29, so we must pass new temporaries. -+ __ resolve_weak_handle(x28, x29); -+ __ mv(t0, x28); -+ -+ __ pop_reg(RegSet::of(x28, x29), sp); -+ -+ __ bnez(t0, method_live); -+ -+ __ bind(bad_call); -+ -+ __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -+ __ bind(method_live); -+} diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp new file mode 100644 -index 00000000000..b85f7f5582b +index 0000000000..984d94f4c3 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp -@@ -0,0 +1,79 @@ +@@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -16336,7 +14082,6 @@ index 00000000000..b85f7f5582b + +#include "asm/macroAssembler.hpp" +#include "gc/shared/barrierSet.hpp" -+#include "gc/shared/barrierSetNMethod.hpp" +#include "memory/allocation.hpp" +#include "oops/access.hpp" + @@ -16379,195 +14124,16 @@ index 00000000000..b85f7f5582b + ); + virtual void barrier_stubs_init() {} + -+ virtual void nmethod_entry_barrier(MacroAssembler* masm); -+ virtual void c2i_entry_barrier(MacroAssembler* masm); + virtual ~BarrierSetAssembler() {} +}; + +#endif // CPU_RISCV_GC_SHARED_BARRIERSETASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp -new file mode 100644 -index 00000000000..ae7ee4c5a44 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp -@@ -0,0 +1,171 @@ -+/* -+ * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "code/codeCache.hpp" -+#include "code/nativeInst.hpp" -+#include "gc/shared/barrierSetNMethod.hpp" -+#include "logging/log.hpp" -+#include "memory/resourceArea.hpp" -+#include "runtime/sharedRuntime.hpp" -+#include "runtime/registerMap.hpp" -+#include "runtime/thread.hpp" -+#include "utilities/align.hpp" -+#include "utilities/debug.hpp" -+ -+class NativeNMethodBarrier: public NativeInstruction { -+ address instruction_address() const { return addr_at(0); } -+ -+ int *guard_addr() { -+ /* auipc + lwu + fence + lwu + beq + lui + addi + slli + addi + slli + jalr + j */ -+ return reinterpret_cast(instruction_address() + 12 * 4); -+ } -+ -+public: -+ int get_value() { -+ return Atomic::load_acquire(guard_addr()); -+ } -+ -+ void set_value(int value) { -+ Atomic::release_store(guard_addr(), value); -+ } -+ -+ void verify() const; -+}; -+ -+// Store the instruction bitmask, bits and name for checking the barrier. -+struct CheckInsn { -+ uint32_t mask; -+ uint32_t bits; -+ const char *name; -+}; -+ -+static const struct CheckInsn barrierInsn[] = { -+ { 0x00000fff, 0x00000297, "auipc t0, 0 "}, -+ { 0x000fffff, 0x0002e283, "lwu t0, 48(t0) "}, -+ { 0xffffffff, 0x0aa0000f, "fence ir, ir "}, -+ { 0x000fffff, 0x000be303, "lwu t1, 112(xthread)"}, -+ { 0x01fff07f, 0x00628063, "beq t0, t1, skip "}, -+ { 0x00000fff, 0x000002b7, "lui t0, imm0 "}, -+ { 0x000fffff, 0x00028293, "addi t0, t0, imm1 "}, -+ { 0xffffffff, 0x00b29293, "slli t0, t0, 11 "}, -+ { 0x000fffff, 0x00028293, "addi t0, t0, imm2 "}, -+ { 0xffffffff, 0x00529293, "slli t0, t0, 5 "}, -+ { 0x000fffff, 0x000280e7, "jalr ra, imm3(t0) "}, -+ { 0x00000fff, 0x0000006f, "j skip "} -+ /* guard: */ -+ /* 32bit nmethod guard value */ -+ /* skip: */ -+}; -+ -+// The encodings must match the instructions emitted by -+// BarrierSetAssembler::nmethod_entry_barrier. The matching ignores the specific -+// register numbers and immediate values in the encoding. -+void NativeNMethodBarrier::verify() const { -+ intptr_t addr = (intptr_t) instruction_address(); -+ for(unsigned int i = 0; i < sizeof(barrierInsn)/sizeof(struct CheckInsn); i++ ) { -+ uint32_t inst = *((uint32_t*) addr); -+ if ((inst & barrierInsn[i].mask) != barrierInsn[i].bits) { -+ tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", addr, inst); -+ fatal("not an %s instruction.", barrierInsn[i].name); -+ } -+ addr += 4; -+ } -+} -+ -+ -+/* We're called from an nmethod when we need to deoptimize it. We do -+ this by throwing away the nmethod's frame and jumping to the -+ ic_miss stub. This looks like there has been an IC miss at the -+ entry of the nmethod, so we resolve the call, which will fall back -+ to the interpreter if the nmethod has been unloaded. */ -+void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { -+ -+ typedef struct { -+ intptr_t *sp; intptr_t *fp; address ra; address pc; -+ } frame_pointers_t; -+ -+ frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5); -+ -+ JavaThread *thread = JavaThread::current(); -+ RegisterMap reg_map(thread, false); -+ frame frame = thread->last_frame(); -+ -+ assert(frame.is_compiled_frame() || frame.is_native_frame(), "must be"); -+ assert(frame.cb() == nm, "must be"); -+ frame = frame.sender(®_map); -+ -+ LogTarget(Trace, nmethod, barrier) out; -+ if (out.is_enabled()) { -+ ResourceMark mark; -+ log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", -+ nm->method()->name_and_sig_as_C_string(), -+ nm, *(address *) return_address_ptr, nm->is_osr_method(), thread, -+ thread->name(), frame.sp(), nm->verified_entry_point()); -+ } -+ -+ new_frame->sp = frame.sp(); -+ new_frame->fp = frame.fp(); -+ new_frame->ra = frame.pc(); -+ new_frame->pc = SharedRuntime::get_handle_wrong_method_stub(); -+} -+ -+// This is the offset of the entry barrier from where the frame is completed. -+// If any code changes between the end of the verified entry where the entry -+// barrier resides, and the completion of the frame, then -+// NativeNMethodCmpBarrier::verify() will immediately complain when it does -+// not find the expected native instruction at this offset, which needs updating. -+// Note that this offset is invariant of PreserveFramePointer. -+ -+// see BarrierSetAssembler::nmethod_entry_barrier -+// auipc + lwu + fence + lwu + beq + movptr_with_offset(5 instructions) + jalr + j + int32 -+static const int entry_barrier_offset = -4 * 13; -+ -+static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { -+ address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset; -+ NativeNMethodBarrier* barrier = reinterpret_cast(barrier_address); -+ debug_only(barrier->verify()); -+ return barrier; -+} -+ -+void BarrierSetNMethod::disarm(nmethod* nm) { -+ if (!supports_entry_barrier(nm)) { -+ return; -+ } -+ -+ // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. -+ NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); -+ -+ barrier->set_value(disarmed_value()); -+} -+ -+bool BarrierSetNMethod::is_armed(nmethod* nm) { -+ if (!supports_entry_barrier(nm)) { -+ return false; -+ } -+ -+ NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); -+ return barrier->get_value() != disarmed_value(); -+} diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp new file mode 100644 -index 00000000000..a419f92b5f6 +index 0000000000..671cad68b2 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -@@ -0,0 +1,111 @@ +@@ -0,0 +1,122 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -16606,12 +14172,15 @@ index 00000000000..a419f92b5f6 + + +void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Register tmp) { -+ assert_cond(masm != NULL); + assert_different_registers(obj, tmp); + BarrierSet* bs = BarrierSet::barrier_set(); + assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); + -+ __ srli(obj, obj, CardTable::card_shift()); ++ CardTableBarrierSet* ctbs = barrier_set_cast(bs); ++ CardTable* ct = ctbs->card_table(); ++ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); ++ ++ __ srli(obj, obj, CardTable::card_shift); + + assert(CardTable::dirty_card_val() == 0, "must be"); + @@ -16626,16 +14195,22 @@ index 00000000000..a419f92b5f6 + __ sb(zr, Address(tmp)); + __ bind(L_already_dirty); + } else { ++ if (ct->scanned_concurrently()) { ++ __ membar(MacroAssembler::StoreStore); ++ } + __ sb(zr, Address(tmp)); + } +} + +void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, + Register start, Register count, Register tmp, RegSet saved_regs) { -+ assert_cond(masm != NULL); + assert_different_registers(start, tmp); + assert_different_registers(count, tmp); + ++ BarrierSet* bs = BarrierSet::barrier_set(); ++ CardTableBarrierSet* ctbs = barrier_set_cast(bs); ++ CardTable* ct = ctbs->card_table(); ++ + Label L_loop, L_done; + const Register end = count; + @@ -16644,12 +14219,15 @@ index 00000000000..a419f92b5f6 + __ shadd(end, count, start, count, LogBytesPerHeapOop); + __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive + -+ __ srli(start, start, CardTable::card_shift()); -+ __ srli(end, end, CardTable::card_shift()); ++ __ srli(start, start, CardTable::card_shift); ++ __ srli(end, end, CardTable::card_shift); + __ sub(count, end, start); // number of bytes to copy + + __ load_byte_map_base(tmp); + __ add(start, start, tmp); ++ if (ct->scanned_concurrently()) { ++ __ membar(MacroAssembler::StoreStore); ++ } + + __ bind(L_loop); + __ add(tmp, start, count); @@ -16673,7 +14251,6 @@ index 00000000000..a419f92b5f6 + if (!precise || dst.offset() == 0) { + store_check(masm, dst.base(), x13); + } else { -+ assert_cond(masm != NULL); + __ la(x13, dst); + store_check(masm, x13, t0); + } @@ -16681,7 +14258,7 @@ index 00000000000..a419f92b5f6 +} diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp new file mode 100644 -index 00000000000..686fe8fa478 +index 0000000000..686fe8fa47 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.hpp @@ -0,0 +1,42 @@ @@ -16729,13 +14306,13 @@ index 00000000000..686fe8fa478 +#endif // #ifndef CPU_RISCV_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp new file mode 100644 -index 00000000000..7aa2015f9ec +index 0000000000..4b7982eb21 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp -@@ -0,0 +1,55 @@ +@@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. ++ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -16766,7 +14343,6 @@ index 00000000000..7aa2015f9ec + +void ModRefBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) { -+ + if (is_oop) { + gen_write_ref_array_pre_barrier(masm, decorators, dst, count, saved_regs); + } @@ -16790,7 +14366,7 @@ index 00000000000..7aa2015f9ec +} diff --git a/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp new file mode 100644 -index 00000000000..00419c3163c +index 0000000000..00419c3163 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.hpp @@ -0,0 +1,55 @@ @@ -16851,7 +14427,7 @@ index 00000000000..00419c3163c +#endif // CPU_RISCV_GC_SHARED_MODREFBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp new file mode 100644 -index 00000000000..cd568cc723f +index 0000000000..d19f5b859c --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp @@ -0,0 +1,117 @@ @@ -16960,7 +14536,7 @@ index 00000000000..cd568cc723f + __ xchg(access.resolved_addr(), value_opr, result, tmp); + + if (access.is_oop()) { -+ result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0), access.decorators()); ++ result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0)); + LIR_Opr tmp_opr = gen->new_register(type); + __ move(result, tmp_opr); + result = tmp_opr; @@ -16974,10 +14550,10 @@ index 00000000000..cd568cc723f +} diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp new file mode 100644 -index 00000000000..d0ac6e52436 +index 0000000000..d73ea36b24 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -@@ -0,0 +1,712 @@ +@@ -0,0 +1,715 @@ +/* + * Copyright (c) 2018, 2020, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -17007,7 +14583,7 @@ index 00000000000..d0ac6e52436 +#include "gc/shenandoah/shenandoahBarrierSet.hpp" +#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" +#include "gc/shenandoah/shenandoahForwarding.hpp" -+#include "gc/shenandoah/shenandoahHeap.inline.hpp" ++#include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahHeapRegion.hpp" +#include "gc/shenandoah/shenandoahRuntime.hpp" +#include "gc/shenandoah/shenandoahThreadLocalData.hpp" @@ -17024,6 +14600,8 @@ index 00000000000..d0ac6e52436 + +#define __ masm-> + ++address ShenandoahBarrierSetAssembler::_shenandoah_lrb = NULL; ++ +void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, + Register src, Register dst, Register count, RegSet saved_regs) { + if (is_oop) { @@ -17096,10 +14674,10 @@ index 00000000000..d0ac6e52436 + Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); + + // Is marking active? -+ if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { ++ if (in_bytes(ShenandoahSATBMarkQueue::byte_width_of_active()) == 4) { + __ lwu(tmp, in_progress); + } else { -+ assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); ++ assert(in_bytes(ShenandoahSATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); + __ lbu(tmp, in_progress); + } + __ beqz(tmp, done); @@ -17196,46 +14774,30 @@ index 00000000000..d0ac6e52436 + Label done; + __ ld(tmp, Address(dst, oopDesc::mark_offset_in_bytes())); + __ xori(tmp, tmp, -1); // eon with 0 is equivalent to XOR with -1 -+ __ andi(t2, tmp, markWord::lock_mask_in_place); ++ __ andi(t2, tmp, markOopDesc::lock_mask_in_place); + __ bnez(t2, done); -+ __ ori(tmp, tmp, markWord::marked_value); ++ __ ori(tmp, tmp, markOopDesc::marked_value); + __ xori(dst, tmp, -1); // eon with 0 is equivalent to XOR with -1 + __ bind(done); + + __ pop_reg(saved_regs, sp); +} + -+void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, -+ Register dst, -+ Address load_addr, -+ DecoratorSet decorators) { ++void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, ++ Register dst, ++ Address load_addr) { + assert(ShenandoahLoadRefBarrier, "Should be enabled"); + assert(dst != t1 && load_addr.base() != t1, "need t1"); + assert_different_registers(load_addr.base(), t0, t1); + -+ bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -+ bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -+ bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -+ bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -+ bool is_narrow = UseCompressedOops && !is_native; -+ -+ Label heap_stable, not_cset; ++ Label done; + __ enter(); + Address gc_state(xthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + __ lbu(t1, gc_state); + + // Check for heap stability -+ if (is_strong) { -+ __ andi(t1, t1, ShenandoahHeap::HAS_FORWARDED); -+ __ beqz(t1, heap_stable); -+ } else { -+ Label lrb; -+ __ andi(t0, t1, ShenandoahHeap::WEAK_ROOTS); -+ __ bnez(t0, lrb); -+ __ andi(t0, t1, ShenandoahHeap::HAS_FORWARDED); -+ __ beqz(t0, heap_stable); -+ __ bind(lrb); -+ } ++ __ andi(t1, t1, ShenandoahHeap::HAS_FORWARDED); ++ __ beqz(t1, done); + + // use x11 for load address + Register result_dst = dst; @@ -17250,43 +14812,12 @@ index 00000000000..d0ac6e52436 + __ la(x11, load_addr); + __ mv(x10, dst); + -+ // Test for in-cset -+ if (is_strong) { -+ __ li(t1, (uint64_t)ShenandoahHeap::in_cset_fast_test_addr()); -+ __ srli(t0, x10, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -+ __ add(t1, t1, t0); -+ __ lbu(t1, Address(t1)); -+ __ andi(t0, t1, 1); -+ __ beqz(t0, not_cset); -+ } ++ __ far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_lrb()))); + -+ __ push_call_clobbered_registers(); -+ if (is_strong) { -+ if (is_narrow) { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); -+ } else { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -+ } -+ } else if (is_weak) { -+ if (is_narrow) { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); -+ } else { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -+ } -+ } else { -+ assert(is_phantom, "only remaining strength"); -+ assert(!is_narrow, "phantom access cannot be narrow"); -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -+ } -+ __ jalr(ra); -+ __ mv(t0, x10); -+ __ pop_call_clobbered_registers(); -+ __ mv(x10, t0); -+ __ bind(not_cset); + __ mv(result_dst, x10); + __ pop_reg(saved_regs, sp); + -+ __ bind(heap_stable); ++ __ bind(done); + __ leave(); +} + @@ -17300,6 +14831,15 @@ index 00000000000..d0ac6e52436 + } +} + ++void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr) { ++ if (ShenandoahLoadRefBarrier) { ++ Label is_null; ++ __ beqz(dst, is_null); ++ load_reference_barrier_not_null(masm, dst, load_addr); ++ __ bind(is_null); ++ } ++} ++ +// +// Arguments: +// @@ -17343,7 +14883,7 @@ index 00000000000..d0ac6e52436 + + BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); + -+ load_reference_barrier(masm, dst, src, decorators); ++ load_reference_barrier(masm, dst, src); + + if (dst != result_dst) { + __ mv(result_dst, dst); @@ -17502,7 +15042,7 @@ index 00000000000..d0ac6e52436 + if (is_cae) { + __ mv(result, expected); + } else { -+ __ addi(result, zr, 1); ++ __ mv(result, 1); + } + __ j(done); + @@ -17535,7 +15075,7 @@ index 00000000000..d0ac6e52436 + Register pre_val_reg = stub->pre_val()->as_register(); + + if (stub->do_load()) { -+ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); ++ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */, false /*unaligned*/); + } + __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); + ce->store_parameter(stub->pre_val()->as_register(), 0); @@ -17548,12 +15088,6 @@ index 00000000000..d0ac6e52436 + ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); + __ bind(*stub->entry()); + -+ DecoratorSet decorators = stub->decorators(); -+ bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -+ bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -+ bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -+ bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -+ + Register obj = stub->obj()->as_register(); + Register res = stub->result()->as_register(); + Register addr = stub->addr()->as_pointer_register(); @@ -17567,30 +15101,32 @@ index 00000000000..d0ac6e52436 + __ mv(res, obj); + } + -+ if (is_strong) { -+ // Check for object in cset. -+ __ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr()); -+ __ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -+ __ add(tmp2, tmp2, tmp1); -+ __ lbu(tmp2, Address(tmp2)); -+ __ beqz(tmp2, *stub->continuation(), true /* is_far */); -+ } ++ // Check for null. ++ __ beqz(res, *stub->continuation(), /* is_far */ true); + ++ // Check for object in cset. ++ __ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr()); ++ __ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint()); ++ __ add(t0, tmp2, tmp1); ++ __ lb(tmp2, Address(t0)); ++ __ beqz(tmp2, *stub->continuation(), /* is_far */ true); ++ ++ // Check if object is already forwarded. ++ Label slow_path; ++ __ ld(tmp1, Address(res, oopDesc::mark_offset_in_bytes())); ++ __ xori(tmp1, tmp1, -1); ++ __ andi(t0, tmp1, markOopDesc::lock_mask_in_place); ++ __ bnez(t0, slow_path); ++ ++ // Decode forwarded object. ++ __ ori(tmp1, tmp1, markOopDesc::marked_value); ++ __ xori(res, tmp1, -1); ++ __ j(*stub->continuation()); ++ ++ __ bind(slow_path); + ce->store_parameter(res, 0); + ce->store_parameter(addr, 1); -+ -+ if (is_strong) { -+ if (is_native) { -+ __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin())); -+ } else { -+ __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_rt_code_blob()->code_begin())); -+ } -+ } else if (is_weak) { -+ __ far_call(RuntimeAddress(bs->load_reference_barrier_weak_rt_code_blob()->code_begin())); -+ } else { -+ assert(is_phantom, "only remaining strength"); -+ __ far_call(RuntimeAddress(bs->load_reference_barrier_phantom_rt_code_blob()->code_begin())); -+ } ++ __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); + + __ j(*stub->continuation()); +} @@ -17644,8 +15180,7 @@ index 00000000000..d0ac6e52436 + __ epilogue(); +} + -+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, -+ DecoratorSet decorators) { ++void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) { + __ prologue("shenandoah_load_reference_barrier", false); + // arg0 : object to be resolved + @@ -17653,31 +15188,10 @@ index 00000000000..d0ac6e52436 + __ load_parameter(0, x10); + __ load_parameter(1, x11); + -+ bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -+ bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -+ bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -+ bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -+ if (is_strong) { -+ if (is_native) { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -+ } else { -+ if (UseCompressedOops) { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); -+ } else { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -+ } -+ } -+ } else if (is_weak) { -+ assert(!is_native, "weak must not be called off-heap"); -+ if (UseCompressedOops) { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); -+ } else { -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -+ } ++ if (UseCompressedOops) { ++ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow)); + } else { -+ assert(is_phantom, "only remaining strength"); -+ assert(is_native, "phantom must only be called off-heap"); -+ __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_phantom); ++ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier)); + } + __ jalr(ra); + __ mv(t0, x10); @@ -17690,12 +15204,77 @@ index 00000000000..d0ac6e52436 +#undef __ + +#endif // COMPILER1 ++ ++address ShenandoahBarrierSetAssembler::shenandoah_lrb() { ++ assert(_shenandoah_lrb != NULL, "need load reference barrier stub"); ++ return _shenandoah_lrb; ++} ++ ++#define __ cgen->assembler()-> ++ ++// Shenandoah load reference barrier. ++// ++// Input: ++// x10: OOP to evacuate. Not null. ++// x11: load address ++// ++// Output: ++// x10: Pointer to evacuated OOP. ++// ++// Trash t0 t1 Preserve everything else. ++address ShenandoahBarrierSetAssembler::generate_shenandoah_lrb(StubCodeGenerator* cgen) { ++ __ align(6); ++ StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb"); ++ address start = __ pc(); ++ ++ Label slow_path; ++ __ mv(t1, ShenandoahHeap::in_cset_fast_test_addr()); ++ __ srli(t0, x10, ShenandoahHeapRegion::region_size_bytes_shift_jint()); ++ __ add(t1, t1, t0); ++ __ lbu(t1, Address(t1, 0)); ++ __ andi(t0, t1, 1); ++ __ bnez(t0, slow_path); ++ __ ret(); ++ ++ __ bind(slow_path); ++ __ enter(); // required for proper stackwalking of RuntimeStub frame ++ ++ __ push_call_clobbered_registers(); ++ ++ if (UseCompressedOops) { ++ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow)); ++ } else { ++ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier)); ++ } ++ __ jalr(ra); ++ __ mv(t0, x10); ++ __ pop_call_clobbered_registers(); ++ __ mv(x10, t0); ++ ++ __ leave(); // required for proper stackwalking of RuntimeStub frame ++ __ ret(); ++ ++ return start; ++} ++ ++#undef __ ++ ++void ShenandoahBarrierSetAssembler::barrier_stubs_init() { ++ if (ShenandoahLoadRefBarrier) { ++ int stub_code_size = 2048; ++ ResourceMark rm; ++ BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size); ++ CodeBuffer buf(bb); ++ StubCodeGenerator cgen(&buf); ++ _shenandoah_lrb = generate_shenandoah_lrb(&cgen); ++ } ++} diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp new file mode 100644 -index 00000000000..a705f497667 +index 0000000000..5d75035e9d --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp -@@ -0,0 +1,88 @@ +@@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -17738,6 +15317,8 @@ index 00000000000..a705f497667 +class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { +private: + ++ static address _shenandoah_lrb; ++ + void satb_write_barrier_pre(MacroAssembler* masm, + Register obj, + Register pre_val, @@ -17755,17 +15336,22 @@ index 00000000000..a705f497667 + + void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg); + void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg); -+ void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr, DecoratorSet decorators); ++ void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr); ++ void load_reference_barrier_not_null(MacroAssembler* masm, Register dst, Address load_addr); ++ ++ address generate_shenandoah_lrb(StubCodeGenerator* cgen); + +public: + ++ static address shenandoah_lrb(); ++ + void iu_barrier(MacroAssembler* masm, Register dst, Register tmp); + +#ifdef COMPILER1 + void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); + void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub); + void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); -+ void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators); ++ void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm); +#endif + + virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, @@ -17779,17 +15365,19 @@ index 00000000000..a705f497667 + virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, + Register obj, Register tmp, Label& slowpath); + -+ void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, ++ virtual void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, + Assembler::Aqrl acquire, Assembler::Aqrl release, bool is_cae, Register result); ++ ++ virtual void barrier_stubs_init(); +}; + +#endif // CPU_RISCV_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad new file mode 100644 -index 00000000000..6c855f23c2a +index 0000000000..bab407a8b7 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad -@@ -0,0 +1,285 @@ +@@ -0,0 +1,197 @@ +// +// Copyright (c) 2018, Red Hat, Inc. All rights reserved. +// Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -17968,48 +15556,6 @@ index 00000000000..6c855f23c2a + ins_pipe(pipe_slow); +%} + -+instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ -+ predicate(needs_acquiring_load_reserved(n)); -+ match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); -+ ins_cost(10 * DEFAULT_COST); -+ -+ effect(TEMP_DEF res, TEMP tmp, KILL cr); -+ format %{ -+ "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq_shenandoah" -+ %} -+ -+ ins_encode %{ -+ Register tmp = $tmp$$Register; -+ __ mv(tmp, $oldval$$Register); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, -+ true /* is_cae */, $res$$Register); -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ -+ predicate(needs_acquiring_load_reserved(n)); -+ match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); -+ ins_cost(10 * DEFAULT_COST); -+ -+ effect(TEMP_DEF res, TEMP tmp, KILL cr); -+ format %{ -+ "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq_shenandoah" -+ %} -+ -+ ins_encode %{ -+ Register tmp = $tmp$$Register; -+ __ mv(tmp, $oldval$$Register); -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, -+ true /* is_cae */, $res$$Register); -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ +instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ + match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); + ins_cost(10 * DEFAULT_COST); @@ -18029,1111 +15575,12 @@ index 00000000000..6c855f23c2a + + ins_pipe(pipe_slow); +%} -+ -+instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ -+ predicate(needs_acquiring_load_reserved(n)); -+ match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); -+ ins_cost(10 * DEFAULT_COST); -+ -+ effect(TEMP tmp, KILL cr); -+ format %{ -+ "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapNAcq_shenandoah" -+ "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" -+ %} -+ -+ ins_encode %{ -+ Register tmp = $tmp$$Register; -+ __ mv(tmp, $oldval$$Register); // Must not clobber oldval. -+ // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, -+ false /* is_cae */, $res$$Register); -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ -+ predicate(needs_acquiring_load_reserved(n)); -+ match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); -+ ins_cost(10 * DEFAULT_COST); -+ -+ effect(TEMP tmp, KILL cr); -+ format %{ -+ "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapPAcq_shenandoah" -+ "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" -+ %} -+ -+ ins_encode %{ -+ Register tmp = $tmp$$Register; -+ __ mv(tmp, $oldval$$Register); // Must not clobber oldval. -+ // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop -+ ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, -+ false /* is_cae */, $res$$Register); -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp -new file mode 100644 -index 00000000000..3d3f4d4d774 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp -@@ -0,0 +1,441 @@ -+/* -+ * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "asm/macroAssembler.inline.hpp" -+#include "code/codeBlob.hpp" -+#include "code/vmreg.inline.hpp" -+#include "gc/z/zBarrier.inline.hpp" -+#include "gc/z/zBarrierSet.hpp" -+#include "gc/z/zBarrierSetAssembler.hpp" -+#include "gc/z/zBarrierSetRuntime.hpp" -+#include "gc/z/zThreadLocalData.hpp" -+#include "memory/resourceArea.hpp" -+#include "runtime/sharedRuntime.hpp" -+#include "utilities/macros.hpp" -+#ifdef COMPILER1 -+#include "c1/c1_LIRAssembler.hpp" -+#include "c1/c1_MacroAssembler.hpp" -+#include "gc/z/c1/zBarrierSetC1.hpp" -+#endif // COMPILER1 -+#ifdef COMPILER2 -+#include "gc/z/c2/zBarrierSetC2.hpp" -+#endif // COMPILER2 -+ -+#ifdef PRODUCT -+#define BLOCK_COMMENT(str) /* nothing */ -+#else -+#define BLOCK_COMMENT(str) __ block_comment(str) -+#endif -+ -+#undef __ -+#define __ masm-> -+ -+void ZBarrierSetAssembler::load_at(MacroAssembler* masm, -+ DecoratorSet decorators, -+ BasicType type, -+ Register dst, -+ Address src, -+ Register tmp1, -+ Register tmp_thread) { -+ if (!ZBarrierSet::barrier_needed(decorators, type)) { -+ // Barrier not needed -+ BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); -+ return; -+ } -+ -+ assert_different_registers(t1, src.base()); -+ assert_different_registers(t0, t1, dst); -+ -+ Label done; -+ -+ // Load bad mask into temp register. -+ __ la(t0, src); -+ __ ld(t1, address_bad_mask_from_thread(xthread)); -+ __ ld(dst, Address(t0)); -+ -+ // Test reference against bad mask. If mask bad, then we need to fix it up. -+ __ andr(t1, dst, t1); -+ __ beqz(t1, done); -+ -+ __ enter(); -+ -+ __ push_call_clobbered_registers_except(RegSet::of(dst)); -+ -+ if (c_rarg0 != dst) { -+ __ mv(c_rarg0, dst); -+ } -+ -+ __ mv(c_rarg1, t0); -+ -+ __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); -+ -+ // Make sure dst has the return value. -+ if (dst != x10) { -+ __ mv(dst, x10); -+ } -+ -+ __ pop_call_clobbered_registers_except(RegSet::of(dst)); -+ __ leave(); -+ -+ __ bind(done); -+} -+ -+#ifdef ASSERT -+ -+void ZBarrierSetAssembler::store_at(MacroAssembler* masm, -+ DecoratorSet decorators, -+ BasicType type, -+ Address dst, -+ Register val, -+ Register tmp1, -+ Register tmp2) { -+ // Verify value -+ if (is_reference_type(type)) { -+ // Note that src could be noreg, which means we -+ // are storing null and can skip verification. -+ if (val != noreg) { -+ Label done; -+ -+ // tmp1 and tmp2 are often set to noreg. -+ RegSet savedRegs = RegSet::of(t0); -+ __ push_reg(savedRegs, sp); -+ -+ __ ld(t0, address_bad_mask_from_thread(xthread)); -+ __ andr(t0, val, t0); -+ __ beqz(t0, done); -+ __ stop("Verify oop store failed"); -+ __ should_not_reach_here(); -+ __ bind(done); -+ __ pop_reg(savedRegs, sp); -+ } -+ } -+ -+ // Store value -+ BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); -+} -+ -+#endif // ASSERT -+ -+void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, -+ DecoratorSet decorators, -+ bool is_oop, -+ Register src, -+ Register dst, -+ Register count, -+ RegSet saved_regs) { -+ if (!is_oop) { -+ // Barrier not needed -+ return; -+ } -+ -+ BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {"); -+ -+ assert_different_registers(src, count, t0); -+ -+ __ push_reg(saved_regs, sp); -+ -+ if (count == c_rarg0 && src == c_rarg1) { -+ // exactly backwards!! -+ __ xorr(c_rarg0, c_rarg0, c_rarg1); -+ __ xorr(c_rarg1, c_rarg0, c_rarg1); -+ __ xorr(c_rarg0, c_rarg0, c_rarg1); -+ } else { -+ __ mv(c_rarg0, src); -+ __ mv(c_rarg1, count); -+ } -+ -+ __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2); -+ -+ __ pop_reg(saved_regs, sp); -+ -+ BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue"); -+} -+ -+void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, -+ Register jni_env, -+ Register robj, -+ Register tmp, -+ Label& slowpath) { -+ BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {"); -+ -+ assert_different_registers(jni_env, robj, tmp); -+ -+ // Resolve jobject -+ BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, robj, tmp, slowpath); -+ -+ // Compute the offset of address bad mask from the field of jni_environment -+ long int bad_mask_relative_offset = (long int) (in_bytes(ZThreadLocalData::address_bad_mask_offset()) - -+ in_bytes(JavaThread::jni_environment_offset())); -+ -+ // Load the address bad mask -+ __ ld(tmp, Address(jni_env, bad_mask_relative_offset)); -+ -+ // Check address bad mask -+ __ andr(tmp, robj, tmp); -+ __ bnez(tmp, slowpath); -+ -+ BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native"); -+} -+ -+#ifdef COMPILER2 -+ -+OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { -+ if (!OptoReg::is_reg(opto_reg)) { -+ return OptoReg::Bad; -+ } -+ -+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -+ if (vm_reg->is_FloatRegister()) { -+ return opto_reg & ~1; -+ } -+ -+ return opto_reg; -+} -+ -+#undef __ -+#define __ _masm-> -+ -+class ZSaveLiveRegisters { -+private: -+ MacroAssembler* const _masm; -+ RegSet _gp_regs; -+ FloatRegSet _fp_regs; -+ VectorRegSet _vp_regs; -+ -+public: -+ void initialize(ZLoadBarrierStubC2* stub) { -+ // Record registers that needs to be saved/restored -+ RegMaskIterator rmi(stub->live()); -+ while (rmi.has_next()) { -+ const OptoReg::Name opto_reg = rmi.next(); -+ if (OptoReg::is_reg(opto_reg)) { -+ const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -+ if (vm_reg->is_Register()) { -+ _gp_regs += RegSet::of(vm_reg->as_Register()); -+ } else if (vm_reg->is_FloatRegister()) { -+ _fp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); -+ } else if (vm_reg->is_VectorRegister()) { -+ const VMReg vm_reg_base = OptoReg::as_VMReg(opto_reg & ~(VectorRegisterImpl::max_slots_per_register - 1)); -+ _vp_regs += VectorRegSet::of(vm_reg_base->as_VectorRegister()); -+ } else { -+ fatal("Unknown register type"); -+ } -+ } -+ } -+ -+ // Remove C-ABI SOE registers, tmp regs and _ref register that will be updated -+ _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2) + RegSet::of(x8, x9) + RegSet::of(x5, stub->ref()); -+ } -+ -+ ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : -+ _masm(masm), -+ _gp_regs(), -+ _fp_regs(), -+ _vp_regs() { -+ // Figure out what registers to save/restore -+ initialize(stub); -+ -+ // Save registers -+ __ push_reg(_gp_regs, sp); -+ __ push_fp(_fp_regs, sp); -+ __ push_vp(_vp_regs, sp); -+ } -+ -+ ~ZSaveLiveRegisters() { -+ // Restore registers -+ __ pop_vp(_vp_regs, sp); -+ __ pop_fp(_fp_regs, sp); -+ __ pop_reg(_gp_regs, sp); -+ } -+}; -+ -+class ZSetupArguments { -+private: -+ MacroAssembler* const _masm; -+ const Register _ref; -+ const Address _ref_addr; -+ -+public: -+ ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : -+ _masm(masm), -+ _ref(stub->ref()), -+ _ref_addr(stub->ref_addr()) { -+ -+ // Setup arguments -+ if (_ref_addr.base() == noreg) { -+ // No self healing -+ if (_ref != c_rarg0) { -+ __ mv(c_rarg0, _ref); -+ } -+ __ mv(c_rarg1, zr); -+ } else { -+ // Self healing -+ if (_ref == c_rarg0) { -+ // _ref is already at correct place -+ __ la(c_rarg1, _ref_addr); -+ } else if (_ref != c_rarg1) { -+ // _ref is in wrong place, but not in c_rarg1, so fix it first -+ __ la(c_rarg1, _ref_addr); -+ __ mv(c_rarg0, _ref); -+ } else if (_ref_addr.base() != c_rarg0) { -+ assert(_ref == c_rarg1, "Mov ref first, vacating c_rarg0"); -+ __ mv(c_rarg0, _ref); -+ __ la(c_rarg1, _ref_addr); -+ } else { -+ assert(_ref == c_rarg1, "Need to vacate c_rarg1 and _ref_addr is using c_rarg0"); -+ if (_ref_addr.base() == c_rarg0) { -+ __ mv(t1, c_rarg1); -+ __ la(c_rarg1, _ref_addr); -+ __ mv(c_rarg0, t1); -+ } else { -+ ShouldNotReachHere(); -+ } -+ } -+ } -+ } -+ -+ ~ZSetupArguments() { -+ // Transfer result -+ if (_ref != x10) { -+ __ mv(_ref, x10); -+ } -+ } -+}; -+ -+#undef __ -+#define __ masm-> -+ -+void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { -+ BLOCK_COMMENT("ZLoadBarrierStubC2"); -+ -+ // Stub entry -+ __ bind(*stub->entry()); -+ -+ { -+ ZSaveLiveRegisters save_live_registers(masm, stub); -+ ZSetupArguments setup_arguments(masm, stub); -+ int32_t offset = 0; -+ __ la_patchable(t0, stub->slow_path(), offset); -+ __ jalr(x1, t0, offset); -+ } -+ -+ // Stub exit -+ __ j(*stub->continuation()); -+} -+ -+#undef __ -+ -+#endif // COMPILER2 -+ -+#ifdef COMPILER1 -+#undef __ -+#define __ ce->masm()-> -+ -+void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce, -+ LIR_Opr ref) const { -+ assert_different_registers(xthread, ref->as_register(), t1); -+ __ ld(t1, address_bad_mask_from_thread(xthread)); -+ __ andr(t1, t1, ref->as_register()); -+} -+ -+void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce, -+ ZLoadBarrierStubC1* stub) const { -+ // Stub entry -+ __ bind(*stub->entry()); -+ -+ Register ref = stub->ref()->as_register(); -+ Register ref_addr = noreg; -+ Register tmp = noreg; -+ -+ if (stub->tmp()->is_valid()) { -+ // Load address into tmp register -+ ce->leal(stub->ref_addr(), stub->tmp()); -+ ref_addr = tmp = stub->tmp()->as_pointer_register(); -+ } else { -+ // Address already in register -+ ref_addr = stub->ref_addr()->as_address_ptr()->base()->as_pointer_register(); -+ } -+ -+ assert_different_registers(ref, ref_addr, noreg); -+ -+ // Save x10 unless it is the result or tmp register -+ // Set up SP to accomodate parameters and maybe x10. -+ if (ref != x10 && tmp != x10) { -+ __ sub(sp, sp, 32); -+ __ sd(x10, Address(sp, 16)); -+ } else { -+ __ sub(sp, sp, 16); -+ } -+ -+ // Setup arguments and call runtime stub -+ ce->store_parameter(ref_addr, 1); -+ ce->store_parameter(ref, 0); -+ -+ __ far_call(stub->runtime_stub()); -+ -+ // Verify result -+ __ verify_oop(x10, "Bad oop"); -+ -+ -+ // Move result into place -+ if (ref != x10) { -+ __ mv(ref, x10); -+ } -+ -+ // Restore x10 unless it is the result or tmp register -+ if (ref != x10 && tmp != x10) { -+ __ ld(x10, Address(sp, 16)); -+ __ add(sp, sp, 32); -+ } else { -+ __ add(sp, sp, 16); -+ } -+ -+ // Stub exit -+ __ j(*stub->continuation()); -+} -+ -+#undef __ -+#define __ sasm-> -+ -+void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, -+ DecoratorSet decorators) const { -+ __ prologue("zgc_load_barrier stub", false); -+ -+ __ push_call_clobbered_registers_except(RegSet::of(x10)); -+ -+ // Setup arguments -+ __ load_parameter(0, c_rarg0); -+ __ load_parameter(1, c_rarg1); -+ -+ __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); -+ -+ __ pop_call_clobbered_registers_except(RegSet::of(x10)); -+ -+ __ epilogue(); -+} -+ -+#undef __ -+#endif // COMPILER1 -diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp -new file mode 100644 -index 00000000000..dc07ab635fe ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp -@@ -0,0 +1,101 @@ -+/* -+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP -+#define CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP -+ -+#include "code/vmreg.hpp" -+#include "oops/accessDecorators.hpp" -+#ifdef COMPILER2 -+#include "opto/optoreg.hpp" -+#endif // COMPILER2 -+ -+#ifdef COMPILER1 -+class LIR_Assembler; -+class LIR_Opr; -+class StubAssembler; -+class ZLoadBarrierStubC1; -+#endif // COMPILER1 -+ -+#ifdef COMPILER2 -+class Node; -+class ZLoadBarrierStubC2; -+#endif // COMPILER2 -+ -+class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase { -+public: -+ virtual void load_at(MacroAssembler* masm, -+ DecoratorSet decorators, -+ BasicType type, -+ Register dst, -+ Address src, -+ Register tmp1, -+ Register tmp_thread); -+ -+#ifdef ASSERT -+ virtual void store_at(MacroAssembler* masm, -+ DecoratorSet decorators, -+ BasicType type, -+ Address dst, -+ Register val, -+ Register tmp1, -+ Register tmp2); -+#endif // ASSERT -+ -+ virtual void arraycopy_prologue(MacroAssembler* masm, -+ DecoratorSet decorators, -+ bool is_oop, -+ Register src, -+ Register dst, -+ Register count, -+ RegSet saved_regs); -+ -+ virtual void try_resolve_jobject_in_native(MacroAssembler* masm, -+ Register jni_env, -+ Register robj, -+ Register tmp, -+ Label& slowpath); -+ -+#ifdef COMPILER1 -+ void generate_c1_load_barrier_test(LIR_Assembler* ce, -+ LIR_Opr ref) const; -+ -+ void generate_c1_load_barrier_stub(LIR_Assembler* ce, -+ ZLoadBarrierStubC1* stub) const; -+ -+ void generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, -+ DecoratorSet decorators) const; -+#endif // COMPILER1 -+ -+#ifdef COMPILER2 -+ OptoReg::Name refine_register(const Node* node, -+ OptoReg::Name opto_reg); -+ -+ void generate_c2_load_barrier_stub(MacroAssembler* masm, -+ ZLoadBarrierStubC2* stub) const; -+#endif // COMPILER2 -+}; -+ -+#endif // CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp -new file mode 100644 -index 00000000000..d14997790af ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp -@@ -0,0 +1,212 @@ -+/* -+ * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "gc/shared/gcLogPrecious.hpp" -+#include "gc/shared/gc_globals.hpp" -+#include "gc/z/zGlobals.hpp" -+#include "runtime/globals.hpp" -+#include "runtime/os.hpp" -+#include "utilities/globalDefinitions.hpp" -+#include "utilities/powerOfTwo.hpp" -+ -+#ifdef LINUX -+#include -+#endif // LINUX -+ -+// -+// The heap can have three different layouts, depending on the max heap size. -+// -+// Address Space & Pointer Layout 1 -+// -------------------------------- -+// -+// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) -+// . . -+// . . -+// . . -+// +--------------------------------+ 0x0000014000000000 (20TB) -+// | Remapped View | -+// +--------------------------------+ 0x0000010000000000 (16TB) -+// . . -+// +--------------------------------+ 0x00000c0000000000 (12TB) -+// | Marked1 View | -+// +--------------------------------+ 0x0000080000000000 (8TB) -+// | Marked0 View | -+// +--------------------------------+ 0x0000040000000000 (4TB) -+// . . -+// +--------------------------------+ 0x0000000000000000 -+// -+// 6 4 4 4 4 -+// 3 6 5 2 1 0 -+// +--------------------+----+-----------------------------------------------+ -+// |00000000 00000000 00|1111|11 11111111 11111111 11111111 11111111 11111111| -+// +--------------------+----+-----------------------------------------------+ -+// | | | -+// | | * 41-0 Object Offset (42-bits, 4TB address space) -+// | | -+// | * 45-42 Metadata Bits (4-bits) 0001 = Marked0 (Address view 4-8TB) -+// | 0010 = Marked1 (Address view 8-12TB) -+// | 0100 = Remapped (Address view 16-20TB) -+// | 1000 = Finalizable (Address view N/A) -+// | -+// * 63-46 Fixed (18-bits, always zero) -+// -+// -+// Address Space & Pointer Layout 2 -+// -------------------------------- -+// -+// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) -+// . . -+// . . -+// . . -+// +--------------------------------+ 0x0000280000000000 (40TB) -+// | Remapped View | -+// +--------------------------------+ 0x0000200000000000 (32TB) -+// . . -+// +--------------------------------+ 0x0000180000000000 (24TB) -+// | Marked1 View | -+// +--------------------------------+ 0x0000100000000000 (16TB) -+// | Marked0 View | -+// +--------------------------------+ 0x0000080000000000 (8TB) -+// . . -+// +--------------------------------+ 0x0000000000000000 -+// -+// 6 4 4 4 4 -+// 3 7 6 3 2 0 -+// +------------------+-----+------------------------------------------------+ -+// |00000000 00000000 0|1111|111 11111111 11111111 11111111 11111111 11111111| -+// +-------------------+----+------------------------------------------------+ -+// | | | -+// | | * 42-0 Object Offset (43-bits, 8TB address space) -+// | | -+// | * 46-43 Metadata Bits (4-bits) 0001 = Marked0 (Address view 8-16TB) -+// | 0010 = Marked1 (Address view 16-24TB) -+// | 0100 = Remapped (Address view 32-40TB) -+// | 1000 = Finalizable (Address view N/A) -+// | -+// * 63-47 Fixed (17-bits, always zero) -+// -+// -+// Address Space & Pointer Layout 3 -+// -------------------------------- -+// -+// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) -+// . . -+// . . -+// . . -+// +--------------------------------+ 0x0000500000000000 (80TB) -+// | Remapped View | -+// +--------------------------------+ 0x0000400000000000 (64TB) -+// . . -+// +--------------------------------+ 0x0000300000000000 (48TB) -+// | Marked1 View | -+// +--------------------------------+ 0x0000200000000000 (32TB) -+// | Marked0 View | -+// +--------------------------------+ 0x0000100000000000 (16TB) -+// . . -+// +--------------------------------+ 0x0000000000000000 -+// -+// 6 4 4 4 4 -+// 3 8 7 4 3 0 -+// +------------------+----+-------------------------------------------------+ -+// |00000000 00000000 |1111|1111 11111111 11111111 11111111 11111111 11111111| -+// +------------------+----+-------------------------------------------------+ -+// | | | -+// | | * 43-0 Object Offset (44-bits, 16TB address space) -+// | | -+// | * 47-44 Metadata Bits (4-bits) 0001 = Marked0 (Address view 16-32TB) -+// | 0010 = Marked1 (Address view 32-48TB) -+// | 0100 = Remapped (Address view 64-80TB) -+// | 1000 = Finalizable (Address view N/A) -+// | -+// * 63-48 Fixed (16-bits, always zero) -+// -+ -+// Default value if probing is not implemented for a certain platform: 128TB -+static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; -+// Minimum value returned, if probing fails: 64GB -+static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; -+ -+static size_t probe_valid_max_address_bit() { -+#ifdef LINUX -+ size_t max_address_bit = 0; -+ const size_t page_size = os::vm_page_size(); -+ for (size_t i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT; --i) { -+ const uintptr_t base_addr = ((uintptr_t) 1U) << i; -+ if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) { -+ // msync suceeded, the address is valid, and maybe even already mapped. -+ max_address_bit = i; -+ break; -+ } -+ if (errno != ENOMEM) { -+ // Some error occured. This should never happen, but msync -+ // has some undefined behavior, hence ignore this bit. -+#ifdef ASSERT -+ fatal("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); -+#else // ASSERT -+ log_warning_p(gc)("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); -+#endif // ASSERT -+ continue; -+ } -+ // Since msync failed with ENOMEM, the page might not be mapped. -+ // Try to map it, to see if the address is valid. -+ void* const result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); -+ if (result_addr != MAP_FAILED) { -+ munmap(result_addr, page_size); -+ } -+ if ((uintptr_t) result_addr == base_addr) { -+ // address is valid -+ max_address_bit = i; -+ break; -+ } -+ } -+ if (max_address_bit == 0) { -+ // probing failed, allocate a very high page and take that bit as the maximum -+ const uintptr_t high_addr = ((uintptr_t) 1U) << DEFAULT_MAX_ADDRESS_BIT; -+ void* const result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); -+ if (result_addr != MAP_FAILED) { -+ max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1; -+ munmap(result_addr, page_size); -+ } -+ } -+ log_info_p(gc, init)("Probing address space for the highest valid bit: " SIZE_FORMAT, max_address_bit); -+ return MAX2(max_address_bit, MINIMUM_MAX_ADDRESS_BIT); -+#else // LINUX -+ return DEFAULT_MAX_ADDRESS_BIT; -+#endif // LINUX -+} -+ -+size_t ZPlatformAddressOffsetBits() { -+ const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; -+ const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; -+ const size_t min_address_offset_bits = max_address_offset_bits - 2; -+ const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); -+ const size_t address_offset_bits = log2i_exact(address_offset); -+ return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); -+} -+ -+size_t ZPlatformAddressMetadataShift() { -+ return ZPlatformAddressOffsetBits(); -+} -diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp -new file mode 100644 -index 00000000000..f20ecd9b073 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp -@@ -0,0 +1,36 @@ -+/* -+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP -+#define CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP -+ -+const size_t ZPlatformGranuleSizeShift = 21; // 2MB -+const size_t ZPlatformHeapViews = 3; -+const size_t ZPlatformCacheLineSize = 64; -+ -+size_t ZPlatformAddressOffsetBits(); -+size_t ZPlatformAddressMetadataShift(); -+ -+#endif // CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad b/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad -new file mode 100644 -index 00000000000..6b6f87814a5 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad -@@ -0,0 +1,233 @@ -+// -+// Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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. -+// -+ -+source_hpp %{ -+ -+#include "gc/shared/gc_globals.hpp" -+#include "gc/z/c2/zBarrierSetC2.hpp" -+#include "gc/z/zThreadLocalData.hpp" -+ -+%} -+ -+source %{ -+ -+static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, int barrier_data) { -+ if (barrier_data == ZLoadBarrierElided) { -+ return; -+ } -+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); -+ __ ld(tmp, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -+ __ andr(tmp, tmp, ref); -+ __ bnez(tmp, *stub->entry(), true /* far */); -+ __ bind(*stub->continuation()); -+} -+ -+static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { -+ ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, ZLoadBarrierStrong); -+ __ j(*stub->entry()); -+ __ bind(*stub->continuation()); -+} -+ -+%} -+ -+// Load Pointer -+instruct zLoadP(iRegPNoSp dst, memory mem) -+%{ -+ match(Set dst (LoadP mem)); -+ predicate(UseZGC && (n->as_Load()->barrier_data() != 0)); -+ effect(TEMP dst); -+ -+ ins_cost(4 * DEFAULT_COST); -+ -+ format %{ "ld $dst, $mem, #@zLoadP" %} -+ -+ ins_encode %{ -+ const Address ref_addr (as_Register($mem$$base), $mem$$disp); -+ __ ld($dst$$Register, ref_addr); -+ z_load_barrier(_masm, this, ref_addr, $dst$$Register, t0 /* tmp */, barrier_data()); -+ %} -+ -+ ins_pipe(iload_reg_mem); -+%} -+ -+instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ -+ match(Set res (CompareAndSwapP mem (Binary oldval newval))); -+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); -+ predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -+ effect(KILL cr, TEMP_DEF res); -+ -+ ins_cost(2 * VOLATILE_REF_COST); -+ -+ format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapP\n\t" -+ "mv $res, $res == $oldval" %} -+ -+ ins_encode %{ -+ Label failed; -+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, -+ true /* result_as_bool */); -+ __ beqz($res$$Register, failed); -+ __ mv(t0, $oldval$$Register); -+ __ bind(failed); -+ if (barrier_data() != ZLoadBarrierElided) { -+ Label good; -+ __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); -+ __ andr(t1, t1, t0); -+ __ beqz(t1, good); -+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, -+ true /* result_as_bool */); -+ __ bind(good); -+ } -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ -+ match(Set res (CompareAndSwapP mem (Binary oldval newval))); -+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); -+ predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong)); -+ effect(KILL cr, TEMP_DEF res); -+ -+ ins_cost(2 * VOLATILE_REF_COST); -+ -+ format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapPAcq\n\t" -+ "mv $res, $res == $oldval" %} -+ -+ ins_encode %{ -+ Label failed; -+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, -+ true /* result_as_bool */); -+ __ beqz($res$$Register, failed); -+ __ mv(t0, $oldval$$Register); -+ __ bind(failed); -+ if (barrier_data() != ZLoadBarrierElided) { -+ Label good; -+ __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); -+ __ andr(t1, t1, t0); -+ __ beqz(t1, good); -+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, -+ true /* result_as_bool */); -+ __ bind(good); -+ } -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ -+ match(Set res (CompareAndExchangeP mem (Binary oldval newval))); -+ predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -+ effect(TEMP_DEF res); -+ -+ ins_cost(2 * VOLATILE_REF_COST); -+ -+ format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangeP" %} -+ -+ ins_encode %{ -+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); -+ if (barrier_data() != ZLoadBarrierElided) { -+ Label good; -+ __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -+ __ andr(t0, t0, $res$$Register); -+ __ beqz(t0, good); -+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); -+ __ bind(good); -+ } -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ -+ match(Set res (CompareAndExchangeP mem (Binary oldval newval))); -+ predicate(UseZGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -+ effect(TEMP_DEF res); -+ -+ ins_cost(2 * VOLATILE_REF_COST); -+ -+ format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangePAcq" %} -+ -+ ins_encode %{ -+ guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); -+ if (barrier_data() != ZLoadBarrierElided) { -+ Label good; -+ __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -+ __ andr(t0, t0, $res$$Register); -+ __ beqz(t0, good); -+ z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); -+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -+ Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); -+ __ bind(good); -+ } -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ -+ match(Set prev (GetAndSetP mem newv)); -+ predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0); -+ effect(TEMP_DEF prev, KILL cr); -+ -+ ins_cost(2 * VOLATILE_REF_COST); -+ -+ format %{ "atomic_xchg $prev, $newv, [$mem], #@zGetAndSetP" %} -+ -+ ins_encode %{ -+ __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base)); -+ z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); -+ %} -+ -+ ins_pipe(pipe_serial); -+%} -+ -+instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ -+ match(Set prev (GetAndSetP mem newv)); -+ predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() != 0)); -+ effect(TEMP_DEF prev, KILL cr); -+ -+ ins_cost(VOLATILE_REF_COST); -+ -+ format %{ "atomic_xchg_acq $prev, $newv, [$mem], #@zGetAndSetPAcq" %} -+ -+ ins_encode %{ -+ __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base)); -+ z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); -+ %} -+ ins_pipe(pipe_serial); -+%} diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp new file mode 100644 -index 00000000000..2936837d951 +index 0000000000..d6ce8da07b --- /dev/null +++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -@@ -0,0 +1,52 @@ +@@ -0,0 +1,46 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. @@ -19169,10 +15616,6 @@ index 00000000000..2936837d951 +// 32-bit integer argument values are extended to 64 bits. +const bool CCallingConventionRequiresIntsAsLongs = false; + -+// RISCV has adopted a multicopy atomic model closely following -+// that of ARMv8. -+#define CPU_MULTI_COPY_ATOMIC -+ +// To be safe, we deoptimize when we come across an access that needs +// patching. This is similar to what is done on aarch64. +#define DEOPTIMIZE_WHEN_PATCHING @@ -19181,17 +15624,15 @@ index 00000000000..2936837d951 + +#define SUPPORT_RESERVED_STACK_AREA + -+#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false -+ -+#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY ++#define THREAD_LOCAL_POLL + +#endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp new file mode 100644 -index 00000000000..cbfc0583883 +index 0000000000..90db2f4460 --- /dev/null +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -0,0 +1,99 @@ +@@ -0,0 +1,111 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -19226,13 +15667,16 @@ index 00000000000..cbfc0583883 +// Sets the default values for platform dependent flags used by the runtime system. +// (see globals.hpp) + ++define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this ++ +define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks +define_pd_global(bool, TrapBasedNullChecks, false); +define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast + -+define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. ++define_pd_global(uintx, CodeCacheSegmentSize, 64 TIERED_ONLY(+64)); // Tiered compilation has large code-entry alignment. +define_pd_global(intx, CodeEntryAlignment, 64); +define_pd_global(intx, OptoLoopAlignment, 16); ++define_pd_global(intx, InlineFrequencyCount, 100); + +#define DEFAULT_STACK_YELLOW_PAGES (2) +#define DEFAULT_STACK_RED_PAGES (1) @@ -19255,8 +15699,13 @@ index 00000000000..cbfc0583883 +define_pd_global(bool, RewriteBytecodes, true); +define_pd_global(bool, RewriteFrequentPairs, true); + ++define_pd_global(bool, UseMembar, true); ++ +define_pd_global(bool, PreserveFramePointer, false); + ++// GC Ergo Flags ++define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread ++ +define_pd_global(uintx, TypeProfileLevel, 111); + +define_pd_global(bool, CompactStrings, true); @@ -19264,13 +15713,18 @@ index 00000000000..cbfc0583883 +// Clear short arrays bigger than one word in an arch-specific way +define_pd_global(intx, InitArrayShortSize, BytesPerLong); + ++define_pd_global(bool, ThreadLocalHandshakes, true); ++ +define_pd_global(intx, InlineSmallCode, 1000); + +#define ARCH_FLAGS(develop, \ + product, \ ++ diagnostic, \ ++ experimental, \ + notproduct, \ + range, \ -+ constraint) \ ++ constraint, \ ++ writeable) \ + \ + product(bool, NearCpool, true, \ + "constant pool is close to instructions") \ @@ -19280,20 +15734,19 @@ index 00000000000..cbfc0583883 + product(bool, TraceTraps, false, "Trace all traps the signal handler") \ + /* For now we're going to be safe and add the I/O bits to userspace fences. */ \ + product(bool, UseConservativeFence, true, \ -+ "Extend i for r and o for w in the pred/succ flags of fence;" \ -+ "Extend fence.i to fence.i + fence.") \ ++ "Extend i for r and o for w in the pred/succ flags of fence") \ + product(bool, AvoidUnalignedAccesses, true, \ + "Avoid generating unaligned memory accesses") \ -+ product(bool, UseRVV, false, EXPERIMENTAL, "Use RVV instructions") \ -+ product(bool, UseRVB, false, EXPERIMENTAL, "Use RVB instructions") \ -+ product(bool, UseRVC, false, EXPERIMENTAL, "Use RVC instructions") \ -+ product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \ -+ "Use RVV instructions for left/right shift of BigInteger") ++ experimental(bool, UseRVV, false, "Use RVV instructions") \ ++ experimental(bool, UseZba, false, "Use Zba instructions") \ ++ experimental(bool, UseZbb, false, "Use Zbb instructions") \ ++ experimental(bool, UseZbs, false, "Use Zbs instructions") \ ++ experimental(bool, UseRVC, false, "Use RVC instructions") + +#endif // CPU_RISCV_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/icBuffer_riscv.cpp b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp new file mode 100644 -index 00000000000..cc93103dc55 +index 0000000000..cc93103dc5 --- /dev/null +++ b/src/hotspot/cpu/riscv/icBuffer_riscv.cpp @@ -0,0 +1,79 @@ @@ -19378,13 +15831,14 @@ index 00000000000..cc93103dc55 +} diff --git a/src/hotspot/cpu/riscv/icache_riscv.cpp b/src/hotspot/cpu/riscv/icache_riscv.cpp new file mode 100644 -index 00000000000..922a80f9f3e +index 0000000000..d615dcfb9e --- /dev/null +++ b/src/hotspot/cpu/riscv/icache_riscv.cpp -@@ -0,0 +1,51 @@ +@@ -0,0 +1,68 @@ +/* -+ * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. ++ * Copyright (c) 2023, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -19409,16 +15863,32 @@ index 00000000000..922a80f9f3e + +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" ++#include "riscv_flush_icache.hpp" ++#include "runtime/java.hpp" +#include "runtime/icache.hpp" + +#define __ _masm-> + +static int icache_flush(address addr, int lines, int magic) { -+ os::icache_flush((long int) addr, (long int) (addr + (lines << ICache::log2_line_size))); ++ // To make a store to instruction memory visible to all RISC-V harts, ++ // the writing hart has to execute a data FENCE before requesting that ++ // all remote RISC-V harts execute a FENCE.I. ++ ++ // We need to make sure stores happens before the I/D cache synchronization. ++ __asm__ volatile("fence rw, rw" : : : "memory"); ++ ++ RiscvFlushIcache::flush((uintptr_t)addr, ((uintptr_t)lines) << ICache::log2_line_size); ++ + return magic; +} + +void ICacheStubGenerator::generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub) { ++ // Only riscv_flush_icache is supported as I-cache synchronization. ++ // We must make sure the VM can execute such without error. ++ if (!RiscvFlushIcache::test()) { ++ vm_exit_during_initialization("Unable to synchronize I-cache"); ++ } ++ + address start = (address)icache_flush; + *flush_icache_stub = (ICache::flush_icache_stub_t)start; + @@ -19435,7 +15905,7 @@ index 00000000000..922a80f9f3e +#undef __ diff --git a/src/hotspot/cpu/riscv/icache_riscv.hpp b/src/hotspot/cpu/riscv/icache_riscv.hpp new file mode 100644 -index 00000000000..5bf40ca8204 +index 0000000000..5bf40ca820 --- /dev/null +++ b/src/hotspot/cpu/riscv/icache_riscv.hpp @@ -0,0 +1,42 @@ @@ -19483,10 +15953,10 @@ index 00000000000..5bf40ca8204 +#endif // CPU_RISCV_ICACHE_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp new file mode 100644 -index 00000000000..d12dcb2af19 +index 0000000000..fa5ddc34b2 --- /dev/null +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -0,0 +1,1940 @@ +@@ -0,0 +1,1931 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -19522,17 +15992,16 @@ index 00000000000..d12dcb2af19 +#include "interpreter/interpreterRuntime.hpp" +#include "logging/log.hpp" +#include "oops/arrayOop.hpp" -+#include "oops/markWord.hpp" +#include "oops/method.hpp" +#include "oops/methodData.hpp" +#include "prims/jvmtiExport.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/basicLock.hpp" ++#include "runtime/biasedLocking.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/safepointMechanism.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/thread.inline.hpp" -+#include "utilities/powerOfTwo.hpp" + +void InterpreterMacroAssembler::narrow(Register result) { + // Get method->_constMethod->_result_type @@ -19785,18 +16254,6 @@ index 00000000000..d12dcb2af19 + ld(klass, Address(klass, Array::base_offset_in_bytes())); +} + -+void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no, -+ Register method, -+ Register cache) { -+ const int method_offset = in_bytes( -+ ConstantPoolCache::base_offset() + -+ ((byte_no == TemplateTable::f2_byte) -+ ? ConstantPoolCacheEntry::f2_offset() -+ : ConstantPoolCacheEntry::f1_offset())); -+ -+ ld(method, Address(cache, method_offset)); // get f1 Method* -+} -+ +// Generate a subtype check: branch to ok_is_subtype if sub_klass is a +// subtype of super_klass. +// @@ -20004,16 +16461,17 @@ index 00000000000..d12dcb2af19 + + Label safepoint; + address* const safepoint_table = Interpreter::safept_table(state); -+ bool needs_thread_local_poll = generate_poll && table != safepoint_table; ++ bool needs_thread_local_poll = generate_poll && ++ SafepointMechanism::uses_thread_local_poll() && table != safepoint_table; + + if (needs_thread_local_poll) { + NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); -+ ld(t1, Address(xthread, JavaThread::polling_word_offset())); ++ ld(t1, Address(xthread, Thread::polling_page_offset())); + andi(t1, t1, SafepointMechanism::poll_bit()); + bnez(t1, safepoint); + } + if (table == Interpreter::dispatch_table(state)) { -+ li(t1, Interpreter::distance_from_dispatch_table(state)); ++ mv(t1, Interpreter::distance_from_dispatch_table(state)); + add(t1, Rs, t1); + shadd(t1, t1, xdispatch, t1, 3); + } else { @@ -20059,7 +16517,6 @@ index 00000000000..d12dcb2af19 + +// remove activation +// -+// Apply stack watermark barrier. +// Unlock the receiver if this is a synchronized method. +// Unlock any Java monitors from syncronized blocks. +// Remove the activation from the stack. @@ -20080,23 +16537,6 @@ index 00000000000..d12dcb2af19 + // result check if synchronized method + Label unlocked, unlock, no_unlock; + -+ // The below poll is for the stack watermark barrier. It allows fixing up frames lazily, -+ // that would normally not be safe to use. Such bad returns into unsafe territory of -+ // the stack, will call InterpreterRuntime::at_unwind. -+ Label slow_path; -+ Label fast_path; -+ safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); -+ j(fast_path); -+ -+ bind(slow_path); -+ push(state); -+ set_last_Java_frame(esp, fp, (address)pc(), t0); -+ super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), xthread); -+ reset_last_Java_frame(true); -+ pop(state); -+ -+ bind(fast_path); -+ + // get the value of _do_not_unlock_if_synchronized into x13 + const Address do_not_unlock_if_synchronized(xthread, + in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); @@ -20288,11 +16728,8 @@ index 00000000000..d12dcb2af19 + // Load object pointer into obj_reg c_rarg3 + ld(obj_reg, Address(lock_reg, obj_offset)); + -+ if (DiagnoseSyncOnValueBasedClasses != 0) { -+ load_klass(tmp, obj_reg); -+ lwu(tmp, Address(tmp, Klass::access_flags_offset())); -+ andi(tmp, tmp, JVM_ACC_IS_VALUE_BASED_CLASS); -+ bnez(tmp, slow_case); ++ if (UseBiasedLocking) { ++ biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp, false, done, &slow_case); + } + + // Load (object->mark() | 1) into swap_reg @@ -20305,7 +16742,17 @@ index 00000000000..d12dcb2af19 + assert(lock_offset == 0, + "displached header must be first word in BasicObjectLock"); + -+ cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, done, /*fallthrough*/NULL); ++ if (PrintBiasedLockingStatistics) { ++ Label fail, fast; ++ cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, fast, &fail); ++ bind(fast); ++ atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), ++ t1, t0); ++ j(done); ++ bind(fail); ++ } else { ++ cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, done, /*fallthrough*/NULL); ++ } + + // Test if the oopMark is an obvious stack pointer, i.e., + // 1) (mark & 7) == 0, and @@ -20317,11 +16764,17 @@ index 00000000000..d12dcb2af19 + // least significant 3 bits clear. + // NOTE: the oopMark is in swap_reg x10 as the result of cmpxchg + sub(swap_reg, swap_reg, sp); -+ li(t0, (int64_t)(7 - os::vm_page_size())); ++ mv(t0, (int64_t)(7 - os::vm_page_size())); + andr(swap_reg, swap_reg, t0); + + // Save the test result, for recursive case, the result is zero + sd(swap_reg, Address(lock_reg, mark_offset)); ++ ++ if (PrintBiasedLockingStatistics) { ++ bnez(swap_reg, slow_case); ++ atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), ++ t1, t0); ++ } + beqz(swap_reg, done); + + bind(slow_case); @@ -20352,7 +16805,9 @@ index 00000000000..d12dcb2af19 + assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1"); + + if (UseHeavyMonitors) { -+ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); ++ call_VM(noreg, ++ CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), ++ lock_reg); + } else { + Label done; + @@ -20372,6 +16827,10 @@ index 00000000000..d12dcb2af19 + // Free entry + sd(zr, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); + ++ if (UseBiasedLocking) { ++ biased_locking_exit(obj_reg, header_reg, done); ++ } ++ + // Load the old header from BasicLock structure + ld(header_reg, Address(swap_reg, + BasicLock::displaced_header_offset_in_bytes())); @@ -20384,7 +16843,9 @@ index 00000000000..d12dcb2af19 + + // Call the runtime routine for slow case. + sd(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // restore obj -+ call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); ++ call_VM(noreg, ++ CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), ++ lock_reg); + + bind(done); + @@ -20404,7 +16865,7 @@ index 00000000000..d12dcb2af19 +void InterpreterMacroAssembler::set_method_data_pointer_for_bcp() { + assert(ProfileInterpreter, "must be profiling interpreter"); + Label set_mdp; -+ push_reg(0xc00, sp); // save x10, x11 ++ push_reg(RegSet::of(x10, x11), sp); // save x10, x11 + + // Test MDO to avoid the call if it is NULL. + ld(x10, Address(xmethod, in_bytes(Method::method_data_offset()))); @@ -20417,7 +16878,7 @@ index 00000000000..d12dcb2af19 + add(x10, x11, x10); + sd(x10, Address(fp, frame::interpreter_frame_mdp_offset * wordSize)); + bind(set_mdp); -+ pop_reg(0xc00, sp); ++ pop_reg(RegSet::of(x10, x11), sp); +} + +void InterpreterMacroAssembler::verify_method_data_pointer() { @@ -21155,7 +17616,7 @@ index 00000000000..d12dcb2af19 + + ld(t0, mdo_addr); + beqz(t0, none); -+ li(tmp, (u1)TypeEntries::null_seen); ++ mv(tmp, (u1)TypeEntries::null_seen); + beq(t0, tmp, none); + // There is a chance that the checks above (re-reading profiling + // data from memory) fail if another thread has just set the @@ -21190,10 +17651,10 @@ index 00000000000..d12dcb2af19 + + lbu(t0, Address(mdp, in_bytes(DataLayout::tag_offset()) - off_to_start)); + if (is_virtual) { -+ li(tmp, (u1)DataLayout::virtual_call_type_data_tag); ++ mv(tmp, (u1)DataLayout::virtual_call_type_data_tag); + bne(t0, tmp, profile_continue); + } else { -+ li(tmp, (u1)DataLayout::call_type_data_tag); ++ mv(tmp, (u1)DataLayout::call_type_data_tag); + bne(t0, tmp, profile_continue); + } + @@ -21223,7 +17684,7 @@ index 00000000000..d12dcb2af19 + mv(index, zr); // index < TypeProfileArgsLimit + bind(loop); + bgtz(index, profileReturnType); -+ li(t0, (int)MethodData::profile_return()); ++ mv(t0, (int)MethodData::profile_return()); + beqz(t0, profileArgument); // (index > 0 || MethodData::profile_return()) == false + bind(profileReturnType); + // If return value type is profiled we may have no argument to profile @@ -21231,7 +17692,7 @@ index 00000000000..d12dcb2af19 + mv(t1, - TypeStackSlotEntries::per_arg_count()); + mul(t1, index, t1); + add(tmp, tmp, t1); -+ li(t1, TypeStackSlotEntries::per_arg_count()); ++ mv(t1, TypeStackSlotEntries::per_arg_count()); + add(t0, mdp, off_to_args); + blt(tmp, t1, done); + @@ -21242,8 +17703,8 @@ index 00000000000..d12dcb2af19 + // stack offset o (zero based) from the start of the argument + // list, for n arguments translates into offset n - o - 1 from + // the end of the argument list -+ li(t0, stack_slot_offset0); -+ li(t1, slot_step); ++ mv(t0, stack_slot_offset0); ++ mv(t1, slot_step); + mul(t1, index, t1); + add(t0, t0, t1); + add(t0, mdp, t0); @@ -21253,8 +17714,8 @@ index 00000000000..d12dcb2af19 + Address arg_addr = argument_address(tmp); + ld(tmp, arg_addr); + -+ li(t0, argument_type_offset0); -+ li(t1, type_step); ++ mv(t0, argument_type_offset0); ++ mv(t1, type_step); + mul(t1, index, t1); + add(t0, t0, t1); + add(mdo_addr, mdp, t0); @@ -21266,7 +17727,7 @@ index 00000000000..d12dcb2af19 + + // increment index by 1 + addi(index, index, 1); -+ li(t1, TypeProfileArgsLimit); ++ mv(t1, TypeProfileArgsLimit); + blt(index, t1, loop); + bind(loopEnd); + @@ -21321,13 +17782,13 @@ index 00000000000..d12dcb2af19 + // length + Label do_profile; + lbu(t0, Address(xbcp, 0)); -+ li(tmp, (u1)Bytecodes::_invokedynamic); ++ mv(tmp, (u1)Bytecodes::_invokedynamic); + beq(t0, tmp, do_profile); -+ li(tmp, (u1)Bytecodes::_invokehandle); ++ mv(tmp, (u1)Bytecodes::_invokehandle); + beq(t0, tmp, do_profile); + get_method(tmp); + lhu(t0, Address(tmp, Method::intrinsic_id_offset_in_bytes())); -+ li(t1, static_cast(vmIntrinsics::_compiledLambdaForm)); ++ mv(t1, vmIntrinsics::_compiledLambdaForm); + bne(t0, t1, profile_continue); + bind(do_profile); + } @@ -21429,10 +17890,10 @@ index 00000000000..d12dcb2af19 +#endif diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp new file mode 100644 -index 00000000000..4d8cb086f82 +index 0000000000..4126e8ee70 --- /dev/null +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp -@@ -0,0 +1,285 @@ +@@ -0,0 +1,283 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. @@ -21557,8 +18018,6 @@ index 00000000000..4d8cb086f82 + // Load cpool->resolved_klass_at(index). + void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp); + -+ void load_resolved_method_at_index(int byte_no, Register method, Register cache); -+ + void pop_ptr(Register r = x10); + void pop_i(Register r = x10); + void pop_l(Register r = x10); @@ -21720,10 +18179,10 @@ index 00000000000..4d8cb086f82 +#endif // CPU_RISCV_INTERP_MASM_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp new file mode 100644 -index 00000000000..d93530d8564 +index 0000000000..b5e6b8c512 --- /dev/null +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp -@@ -0,0 +1,295 @@ +@@ -0,0 +1,305 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -21800,6 +18259,16 @@ index 00000000000..d93530d8564 + _stack_offset = 0; +} + ++// The C ABI specifies: ++// "integer scalars narrower than XLEN bits are widened according to the sign ++// of their type up to 32 bits, then sign-extended to XLEN bits." ++// Applies for both passed in register and stack. ++// ++// Java uses 32-bit stack slots; jint, jshort, jchar, jbyte uses one slot. ++// Native uses 64-bit stack slots for all integer scalar types. ++// ++// lw loads the Java stack slot, sign-extends and ++// sd store this widened integer into a 64 bit native stack slot. +void InterpreterRuntime::SignatureHandlerGenerator::pass_int() { + const Address src(from(), Interpreter::local_offset_in_bytes(offset())); + @@ -21808,7 +18277,7 @@ index 00000000000..d93530d8564 + __ lw(reg, src); + } else { + __ lw(x10, src); -+ __ sw(x10, Address(to(), next_stack_offset())); ++ __ sd(x10, Address(to(), next_stack_offset())); + } +} + @@ -22004,12 +18473,12 @@ index 00000000000..d93530d8564 +}; + + -+JRT_ENTRY(address, -+ InterpreterRuntime::slow_signature_handler(JavaThread* current, ++IRT_ENTRY(address, ++ InterpreterRuntime::slow_signature_handler(JavaThread* thread, + Method* method, + intptr_t* from, + intptr_t* to)) -+ methodHandle m(current, (Method*)method); ++ methodHandle m(thread, (Method*)method); + assert(m->is_native(), "sanity check"); + + // handle arguments @@ -22018,10 +18487,10 @@ index 00000000000..d93530d8564 + + // return result handler + return Interpreter::result_handler(m->result_type()); -+JRT_END ++IRT_END diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp new file mode 100644 -index 00000000000..05df63ba2ae +index 0000000000..05df63ba2a --- /dev/null +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.hpp @@ -0,0 +1,68 @@ @@ -22095,10 +18564,10 @@ index 00000000000..05df63ba2ae +#endif // CPU_RISCV_INTERPRETERRT_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp new file mode 100644 -index 00000000000..9a6084afa1d +index 0000000000..5a0c9b812f --- /dev/null +++ b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp -@@ -0,0 +1,86 @@ +@@ -0,0 +1,89 @@ +/* + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -22184,13 +18653,16 @@ index 00000000000..9a6084afa1d + + intptr_t* last_Java_fp(void) { return _last_Java_fp; } + ++ // Assert (last_Java_sp == NULL || fp == NULL) ++ void set_last_Java_fp(intptr_t* fp) { OrderAccess::release(); _last_Java_fp = fp; } ++ +#endif // CPU_RISCV_JAVAFRAMEANCHOR_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp new file mode 100644 -index 00000000000..814ed23e471 +index 0000000000..f6e7351c4f --- /dev/null +++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp -@@ -0,0 +1,214 @@ +@@ -0,0 +1,194 @@ +/* + * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -22276,28 +18748,10 @@ index 00000000000..814ed23e471 + // An even value means there are no ongoing safepoint operations + __ andi(t0, rcounter, 1); + __ bnez(t0, slow); -+ -+ if (JvmtiExport::can_post_field_access()) { -+ // Using barrier to order wrt. JVMTI check and load of result. -+ __ membar(MacroAssembler::LoadLoad); -+ -+ // Check to see if a field access watch has been set before we -+ // take the fast path. -+ int32_t offset2; -+ __ la_patchable(result, -+ ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), -+ offset2); -+ __ lwu(result, Address(result, offset2)); -+ __ bnez(result, slow); -+ -+ __ mv(robj, c_rarg1); -+ } else { -+ // Using address dependency to order wrt. load of result. -+ __ xorr(robj, c_rarg1, rcounter); -+ __ xorr(robj, robj, rcounter); // obj, since -+ // robj ^ rcounter ^ rcounter == robj -+ // robj is address dependent on rcounter. -+ } ++ __ xorr(robj, c_rarg1, rcounter); ++ __ xorr(robj, robj, rcounter); // obj, since ++ // robj ^ rcounter ^ rcounter == robj ++ // robj is address dependent on rcounter. + + // Both robj and t0 are clobbered by try_resolve_jobject_in_native. + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); @@ -22330,10 +18784,8 @@ index 00000000000..814ed23e471 + default: ShouldNotReachHere(); + } + -+ // Using acquire: Order JVMTI check and load of result wrt. succeeding check -+ // (LoadStore for volatile field). -+ __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); -+ ++ __ xorr(rcounter_addr, rcounter_addr, result); ++ __ xorr(rcounter_addr, rcounter_addr, result); + __ lw(t0, safepoint_counter_addr); + __ bne(rcounter, t0, slow); + @@ -22407,7 +18859,7 @@ index 00000000000..814ed23e471 +} diff --git a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp new file mode 100644 -index 00000000000..83ffcc55d83 +index 0000000000..df3c0267ee --- /dev/null +++ b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp @@ -0,0 +1,106 @@ @@ -22440,7 +18892,6 @@ index 00000000000..83ffcc55d83 +#define CPU_RISCV_JNITYPES_RISCV_HPP + +#include "jni.h" -+#include "memory/allStatic.hpp" +#include "oops/oop.hpp" + +// This file holds platform-dependent routines used to write primitive jni @@ -22479,8 +18930,9 @@ index 00000000000..83ffcc55d83 + } + + // Oops are stored in native format in one JavaCallArgument slot at *to. -+ static inline void put_obj(const Handle& from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle.raw_value(); } -+ static inline void put_obj(jobject from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle; } ++ static inline void put_obj(oop from, intptr_t *to) { *(oop *)(to + 0 ) = from; } ++ static inline void put_obj(oop from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = from; } ++ static inline void put_obj(oop *from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = *from; } + + // Floats are stored in native format in one JavaCallArgument slot at *to. + static inline void put_float(jfloat from, intptr_t *to) { *(jfloat *)(to + 0 ) = from; } @@ -22519,10 +18971,10 @@ index 00000000000..83ffcc55d83 +#endif // CPU_RISCV_JNITYPES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp new file mode 100644 -index 00000000000..86710295444 +index 0000000000..14e07036ac --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -0,0 +1,4016 @@ +@@ -0,0 +1,5390 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -22566,14 +19018,15 @@ index 00000000000..86710295444 +#include "oops/compressedOops.inline.hpp" +#include "oops/klass.inline.hpp" +#include "oops/oop.hpp" ++#include "runtime/biasedLocking.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.inline.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.hpp" -+#include "utilities/powerOfTwo.hpp" +#ifdef COMPILER2 +#include "opto/compile.hpp" ++#include "opto/intrinsicnode.hpp" +#include "opto/node.hpp" +#include "opto/output.hpp" +#endif @@ -22587,28 +19040,24 @@ index 00000000000..86710295444 + +static void pass_arg0(MacroAssembler* masm, Register arg) { + if (c_rarg0 != arg) { -+ assert_cond(masm != NULL); + masm->mv(c_rarg0, arg); + } +} + +static void pass_arg1(MacroAssembler* masm, Register arg) { + if (c_rarg1 != arg) { -+ assert_cond(masm != NULL); + masm->mv(c_rarg1, arg); + } +} + +static void pass_arg2(MacroAssembler* masm, Register arg) { + if (c_rarg2 != arg) { -+ assert_cond(masm != NULL); + masm->mv(c_rarg2, arg); + } +} + +static void pass_arg3(MacroAssembler* masm, Register arg) { + if (c_rarg3 != arg) { -+ assert_cond(masm != NULL); + masm->mv(c_rarg3, arg); + } +} @@ -22716,6 +19165,22 @@ index 00000000000..86710295444 +void MacroAssembler::check_and_handle_earlyret(Register java_thread) {} +void MacroAssembler::check_and_handle_popframe(Register java_thread) {} + ++RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, ++ Register tmp, ++ int offset) { ++ intptr_t value = *delayed_value_addr; ++ if (value != 0) ++ return RegisterOrConstant(value + offset); ++ ++ // load indirectly to solve generation ordering problem ++ ld(tmp, ExternalAddress((address) delayed_value_addr)); ++ ++ if (offset != 0) ++ add(tmp, tmp, offset); ++ ++ return RegisterOrConstant(tmp); ++} ++ +// Calls to C land +// +// When entering C land, the fp, & esp of the last Java frame have to be recorded @@ -22767,12 +19232,35 @@ index 00000000000..86710295444 + if (L.is_bound()) { + set_last_Java_frame(last_java_sp, last_java_fp, target(L), tmp); + } else { -+ InstructionMark im(this); + L.add_patch_at(code(), locator()); + set_last_Java_frame(last_java_sp, last_java_fp, pc() /* Patched later */, tmp); + } +} + ++// Just like safepoint_poll, but use an acquiring load for thread- ++// local polling. ++// ++// We need an acquire here to ensure that any subsequent load of the ++// global SafepointSynchronize::_state flag is ordered after this load ++// of the local Thread::_polling page. We don't want this poll to ++// return false (i.e. not safepointing) and a later poll of the global ++// SafepointSynchronize::_state spuriously to return true. ++// ++// This is to avoid a race when we're in a native->Java transition ++// racing the code which wakes up from a safepoint. ++// ++void MacroAssembler::safepoint_poll_acquire(Label& slow_path) { ++ if (SafepointMechanism::uses_thread_local_poll()) { ++ membar(MacroAssembler::AnyAny); ++ ld(t1, Address(xthread, Thread::polling_page_offset())); ++ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); ++ andi(t0, t1, SafepointMechanism::poll_bit()); ++ bnez(t0, slow_path); ++ } else { ++ safepoint_poll(slow_path); ++ } ++} ++ +void MacroAssembler::reset_last_Java_frame(bool clear_fp) { + // we must set sp to zero to clear frame + sd(zr, Address(xthread, JavaThread::last_Java_sp_offset())); @@ -22857,36 +19345,6 @@ index 00000000000..86710295444 + sd(zr, Address(java_thread, JavaThread::vm_result_2_offset())); +} + -+void MacroAssembler::clinit_barrier(Register klass, Register tmp, Label* L_fast_path, Label* L_slow_path) { -+ assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required"); -+ assert_different_registers(klass, xthread, tmp); -+ -+ Label L_fallthrough, L_tmp; -+ if (L_fast_path == NULL) { -+ L_fast_path = &L_fallthrough; -+ } else if (L_slow_path == NULL) { -+ L_slow_path = &L_fallthrough; -+ } -+ -+ // Fast path check: class is fully initialized -+ lbu(tmp, Address(klass, InstanceKlass::init_state_offset())); -+ sub(tmp, tmp, InstanceKlass::fully_initialized); -+ beqz(tmp, *L_fast_path); -+ -+ // Fast path check: current thread is initializer thread -+ ld(tmp, Address(klass, InstanceKlass::init_thread_offset())); -+ -+ if (L_slow_path == &L_fallthrough) { -+ beq(xthread, tmp, *L_fast_path); -+ bind(*L_slow_path); -+ } else if (L_fast_path == &L_fallthrough) { -+ bne(xthread, tmp, *L_slow_path); -+ bind(*L_fast_path); -+ } else { -+ Unimplemented(); -+ } -+} -+ +void MacroAssembler::verify_oop(Register reg, const char* s) { + if (!VerifyOops) { return; } + @@ -22903,7 +19361,10 @@ index 00000000000..86710295444 + push_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); + + mv(c_rarg0, reg); // c_rarg0 : x10 -+ li(t0, (uintptr_t)(address)b); ++ // The length of the instruction sequence emitted should be independent ++ // of the values of the local char buffer address so that the size of mach ++ // nodes for scratch emit and normal emit matches. ++ movptr(t0, (address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; @@ -22939,7 +19400,10 @@ index 00000000000..86710295444 + ld(x10, addr); + } + -+ li(t0, (uintptr_t)(address)b); ++ // The length of the instruction sequence emitted should be independent ++ // of the values of the local char buffer address so that the size of mach ++ // nodes for scratch emit and normal emit matches. ++ movptr(t0, (address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; @@ -23056,8 +19520,11 @@ index 00000000000..86710295444 +void MacroAssembler::stop(const char* msg) { + address ip = pc(); + pusha(); -+ li(c_rarg0, (uintptr_t)(address)msg); -+ li(c_rarg1, (uintptr_t)(address)ip); ++ // The length of the instruction sequence emitted should be independent ++ // of the values of msg and ip so that the size of mach nodes for scratch ++ // emit and normal emit matches. ++ mv(c_rarg0, (address)msg); ++ mv(c_rarg1, (address)ip); + mv(c_rarg2, sp); + mv(c_rarg3, CAST_FROM_FN_PTR(address, MacroAssembler::debug64)); + jalr(c_rarg3); @@ -23079,7 +19546,6 @@ index 00000000000..86710295444 + // CompiledDirectStaticCall::set_to_interpreted knows the + // exact layout of this stub. + -+ ifence(); + mov_metadata(xmethod, (Metadata*)NULL); + + // Jump to the entry point of the i2c stub. @@ -23091,24 +19557,14 @@ index 00000000000..86710295444 +void MacroAssembler::call_VM_leaf_base(address entry_point, + int number_of_arguments, + Label *retaddr) { -+ call_native_base(entry_point, retaddr); -+} -+ -+void MacroAssembler::call_native(address entry_point, Register arg_0) { -+ pass_arg0(this, arg_0); -+ call_native_base(entry_point); -+} -+ -+void MacroAssembler::call_native_base(address entry_point, Label *retaddr) { -+ Label E, L; + int32_t offset = 0; -+ push_reg(0x80000040, sp); // push << t0 & xmethod >> to sp ++ push_reg(RegSet::of(t0, xmethod), sp); // push << t0 & xmethod >> to sp + movptr_with_offset(t0, entry_point, offset); + jalr(x1, t0, offset); + if (retaddr != NULL) { + bind(*retaddr); + } -+ pop_reg(0x80000040, sp); // pop << t0 & xmethod >> from sp ++ pop_reg(RegSet::of(t0, xmethod), sp); // pop << t0 & xmethod >> from sp +} + +void MacroAssembler::call_VM_leaf(address entry_point, int number_of_arguments) { @@ -23268,15 +19724,13 @@ index 00000000000..86710295444 +} + +void MacroAssembler::la(Register Rd, const Address &adr) { -+ InstructionMark im(this); -+ code_section()->relocate(inst_mark(), adr.rspec()); -+ relocInfo::relocType rtype = adr.rspec().reloc()->type(); -+ + switch (adr.getMode()) { + case Address::literal: { ++ relocInfo::relocType rtype = adr.rspec().reloc()->type(); + if (rtype == relocInfo::none) { -+ li(Rd, (intptr_t)(adr.target())); ++ mv(Rd, (intptr_t)(adr.target())); + } else { ++ relocate(adr.rspec()); + movptr(Rd, adr.target()); + } + break; @@ -23483,7 +19937,7 @@ index 00000000000..86710295444 + return count; +} + -+// Push lots of registers in the bit set supplied. Don't push sp. ++// Push integer registers in the bitset supplied. Don't push sp. +// Return the number of words pushed +int MacroAssembler::push_reg(unsigned int bitset, Register stack) { + DEBUG_ONLY(int words_pushed = 0;) @@ -23495,11 +19949,11 @@ index 00000000000..86710295444 + int offset = is_even(count) ? 0 : wordSize; + + if (count) { -+ addi(stack, stack, - count * wordSize - offset); ++ addi(stack, stack, -count * wordSize - offset); + } + for (int i = count - 1; i >= 0; i--) { + sd(as_Register(regs[i]), Address(stack, (count - 1 - i) * wordSize + offset)); -+ DEBUG_ONLY(words_pushed ++;) ++ DEBUG_ONLY(words_pushed++;) + } + + assert(words_pushed == count, "oops, pushed != count"); @@ -23518,7 +19972,7 @@ index 00000000000..86710295444 + + for (int i = count - 1; i >= 0; i--) { + ld(as_Register(regs[i]), Address(stack, (count - 1 - i) * wordSize + offset)); -+ DEBUG_ONLY(words_popped ++;) ++ DEBUG_ONLY(words_popped++;) + } + + if (count) { @@ -23529,11 +19983,11 @@ index 00000000000..86710295444 + return count; +} + -+// Push float registers in the bitset, except sp. -+// Return the number of heapwords pushed. ++// Push floating-point registers in the bitset supplied. ++// Return the number of words pushed +int MacroAssembler::push_fp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); -+ int words_pushed = 0; ++ DEBUG_ONLY(int words_pushed = 0;) + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + int push_slots = count + (count & 1); @@ -23544,23 +19998,24 @@ index 00000000000..86710295444 + + for (int i = count - 1; i >= 0; i--) { + fsd(as_FloatRegister(regs[i]), Address(stack, (push_slots - 1 - i) * wordSize)); -+ words_pushed++; ++ DEBUG_ONLY(words_pushed++;) + } + + assert(words_pushed == count, "oops, pushed(%d) != count(%d)", words_pushed, count); ++ + return count; +} + +int MacroAssembler::pop_fp(unsigned int bitset, Register stack) { + CompressibleRegion cr(this); -+ int words_popped = 0; ++ DEBUG_ONLY(int words_popped = 0;) + unsigned char regs[32]; + int count = bitset_to_regs(bitset, regs); + int pop_slots = count + (count & 1); + + for (int i = count - 1; i >= 0; i--) { + fld(as_FloatRegister(regs[i]), Address(stack, (pop_slots - 1 - i) * wordSize)); -+ words_popped++; ++ DEBUG_ONLY(words_popped++;) + } + + if (count) { @@ -23568,55 +20023,10 @@ index 00000000000..86710295444 + } + + assert(words_popped == count, "oops, popped(%d) != count(%d)", words_popped, count); ++ + return count; +} + -+#ifdef COMPILER2 -+int MacroAssembler::push_vp(unsigned int bitset, Register stack) { -+ CompressibleRegion cr(this); -+ int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -+ -+ // Scan bitset to accumulate register pairs -+ unsigned char regs[32]; -+ int count = 0; -+ for (int reg = 31; reg >= 0; reg--) { -+ if ((1U << 31) & bitset) { -+ regs[count++] = reg; -+ } -+ bitset <<= 1; -+ } -+ -+ for (int i = 0; i < count; i++) { -+ sub(stack, stack, vector_size_in_bytes); -+ vs1r_v(as_VectorRegister(regs[i]), stack); -+ } -+ -+ return count * vector_size_in_bytes / wordSize; -+} -+ -+int MacroAssembler::pop_vp(unsigned int bitset, Register stack) { -+ CompressibleRegion cr(this); -+ int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -+ -+ // Scan bitset to accumulate register pairs -+ unsigned char regs[32]; -+ int count = 0; -+ for (int reg = 31; reg >= 0; reg--) { -+ if ((1U << 31) & bitset) { -+ regs[count++] = reg; -+ } -+ bitset <<= 1; -+ } -+ -+ for (int i = count - 1; i >= 0; i--) { -+ vl1r_v(as_VectorRegister(regs[i]), stack); -+ add(stack, stack, vector_size_in_bytes); -+ } -+ -+ return count * vector_size_in_bytes / wordSize; -+} -+#endif // COMPILER2 -+ +void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude) { + CompressibleRegion cr(this); + // Push integer registers x7, x10-x17, x28-x31. @@ -23627,7 +20037,7 @@ index 00000000000..86710295444 + int offset = 0; + for (int i = 0; i < 32; i++) { + if (i <= f7->encoding() || i >= f28->encoding() || (i >= f10->encoding() && i <= f17->encoding())) { -+ fsd(as_FloatRegister(i), Address(sp, wordSize * (offset ++))); ++ fsd(as_FloatRegister(i), Address(sp, wordSize * (offset++))); + } + } +} @@ -23637,7 +20047,7 @@ index 00000000000..86710295444 + int offset = 0; + for (int i = 0; i < 32; i++) { + if (i <= f7->encoding() || i >= f28->encoding() || (i >= f10->encoding() && i <= f17->encoding())) { -+ fld(as_FloatRegister(i), Address(sp, wordSize * (offset ++))); ++ fld(as_FloatRegister(i), Address(sp, wordSize * (offset++))); + } + } + addi(sp, sp, wordSize * 20); @@ -23648,47 +20058,29 @@ index 00000000000..86710295444 +// Push all the integer registers, except zr(x0) & sp(x2) & gp(x3) & tp(x4). +void MacroAssembler::pusha() { + CompressibleRegion cr(this); -+ push_reg(0xffffffe2, sp); ++ push_reg(RegSet::of(x1) + RegSet::range(x5, x31), sp); +} + +// Pop all the integer registers, except zr(x0) & sp(x2) & gp(x3) & tp(x4). +void MacroAssembler::popa() { + CompressibleRegion cr(this); -+ pop_reg(0xffffffe2, sp); ++ pop_reg(RegSet::of(x1) + RegSet::range(x5, x31), sp); +} + -+void MacroAssembler::push_CPU_state(bool save_vectors, int vector_size_in_bytes) { ++void MacroAssembler::push_CPU_state() { + CompressibleRegion cr(this); + // integer registers, except zr(x0) & ra(x1) & sp(x2) & gp(x3) & tp(x4) -+ push_reg(0xffffffe0, sp); ++ push_reg(RegSet::range(x5, x31), sp); + + // float registers + addi(sp, sp, - 32 * wordSize); + for (int i = 0; i < 32; i++) { + fsd(as_FloatRegister(i), Address(sp, i * wordSize)); + } -+ -+ // vector registers -+ if (save_vectors) { -+ sub(sp, sp, vector_size_in_bytes * VectorRegisterImpl::number_of_registers); -+ vsetvli(t0, x0, Assembler::e64, Assembler::m8); -+ for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { -+ add(t0, sp, vector_size_in_bytes * i); -+ vse64_v(as_VectorRegister(i), t0); -+ } -+ } +} + -+void MacroAssembler::pop_CPU_state(bool restore_vectors, int vector_size_in_bytes) { ++void MacroAssembler::pop_CPU_state() { + CompressibleRegion cr(this); -+ // vector registers -+ if (restore_vectors) { -+ vsetvli(t0, x0, Assembler::e64, Assembler::m8); -+ for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { -+ vle64_v(as_VectorRegister(i), sp); -+ add(sp, sp, vector_size_in_bytes * 8); -+ } -+ } + + // float registers + for (int i = 0; i < 32; i++) { @@ -23697,7 +20089,7 @@ index 00000000000..86710295444 + addi(sp, sp, 32 * wordSize); + + // integer registers, except zr(x0) & ra(x1) & sp(x2) & gp(x3) & tp(x4) -+ pop_reg(0xffffffe0, sp); ++ pop_reg(RegSet::range(x5, x31), sp); +} + +static int patch_offset_in_jal(address branch, int64_t offset) { @@ -23727,36 +20119,15 @@ index 00000000000..86710295444 + +static int patch_addr_in_movptr(address branch, address target) { + const int MOVPTR_INSTRUCTIONS_NUM = 6; // lui + addi + slli + addi + slli + addi/jalr/load -+ int32_t lower = ((intptr_t)target << 36) >> 36; -+ int64_t upper = ((intptr_t)target - lower) >> 28; -+ Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[47:28] + target[27] ==> branch[31:12] -+ Assembler::patch(branch + 4, 31, 20, (lower >> 16) & 0xfff); // Addi. target[27:16] ==> branch[31:20] -+ Assembler::patch(branch + 12, 31, 20, (lower >> 5) & 0x7ff); // Addi. target[15: 5] ==> branch[31:20] -+ Assembler::patch(branch + 20, 31, 20, lower & 0x1f); // Addi/Jalr/Load. target[ 4: 0] ==> branch[31:20] ++ int32_t lower = ((intptr_t)target << 35) >> 35; ++ int64_t upper = ((intptr_t)target - lower) >> 29; ++ Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[48:29] + target[28] ==> branch[31:12] ++ Assembler::patch(branch + 4, 31, 20, (lower >> 17) & 0xfff); // Addi. target[28:17] ==> branch[31:20] ++ Assembler::patch(branch + 12, 31, 20, (lower >> 6) & 0x7ff); // Addi. target[16: 6] ==> branch[31:20] ++ Assembler::patch(branch + 20, 31, 20, lower & 0x3f); // Addi/Jalr/Load. target[ 5: 0] ==> branch[31:20] + return MOVPTR_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; +} + -+static int patch_imm_in_li64(address branch, address target) { -+ const int LI64_INSTRUCTIONS_NUM = 8; // lui + addi + slli + addi + slli + addi + slli + addi -+ int64_t lower = (intptr_t)target & 0xffffffff; -+ lower = lower - ((lower << 44) >> 44); -+ int64_t tmp_imm = ((uint64_t)((intptr_t)target & 0xffffffff00000000)) + (uint64_t)lower; -+ int32_t upper = (tmp_imm - (int32_t)lower) >> 32; -+ int64_t tmp_upper = upper, tmp_lower = upper; -+ tmp_lower = (tmp_lower << 52) >> 52; -+ tmp_upper -= tmp_lower; -+ tmp_upper >>= 12; -+ // Load upper 32 bits. Upper = target[63:32], but if target[31] = 1 or (target[31:28] == 0x7ff && target[19] == 1), -+ // upper = target[63:32] + 1. -+ Assembler::patch(branch + 0, 31, 12, tmp_upper & 0xfffff); // Lui. -+ Assembler::patch(branch + 4, 31, 20, tmp_lower & 0xfff); // Addi. -+ // Load the rest 32 bits. -+ Assembler::patch(branch + 12, 31, 20, ((int32_t)lower >> 20) & 0xfff); // Addi. -+ Assembler::patch(branch + 20, 31, 20, (((intptr_t)target << 44) >> 52) & 0xfff); // Addi. -+ Assembler::patch(branch + 28, 31, 20, (intptr_t)target & 0xff); // Addi. -+ return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; -+} -+ +static int patch_imm_in_li32(address branch, int32_t target) { + const int LI32_INSTRUCTIONS_NUM = 2; // lui + addiw + int64_t upper = (intptr_t)target; @@ -23804,23 +20175,13 @@ index 00000000000..86710295444 + +static address get_target_of_movptr(address insn_addr) { + assert_cond(insn_addr != NULL); -+ intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 28; // Lui. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 16; // Addi. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 5; // Addi. ++ intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 29; // Lui. ++ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 17; // Addi. ++ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 6; // Addi. + target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[5], 31, 20)); // Addi/Jalr/Load. + return (address) target_address; +} + -+static address get_target_of_li64(address insn_addr) { -+ assert_cond(insn_addr != NULL); -+ intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 44; // Lui. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 32; // Addi. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 20; // Addi. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[5], 31, 20)) << 8; // Addi. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[7], 31, 20)); // Addi. -+ return (address)target_address; -+} -+ +static address get_target_of_li32(address insn_addr) { + assert_cond(insn_addr != NULL); + intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 12; // Lui. @@ -23841,8 +20202,6 @@ index 00000000000..86710295444 + return patch_offset_in_pc_relative(branch, offset); + } else if (NativeInstruction::is_movptr_at(branch)) { // movptr + return patch_addr_in_movptr(branch, target); -+ } else if (NativeInstruction::is_li64_at(branch)) { // li64 -+ return patch_imm_in_li64(branch, target); + } else if (NativeInstruction::is_li32_at(branch)) { // li32 + int64_t imm = (intptr_t)target; + return patch_imm_in_li32(branch, (int32_t)imm); @@ -23868,8 +20227,6 @@ index 00000000000..86710295444 + offset = get_offset_of_pc_relative(insn_addr); + } else if (NativeInstruction::is_movptr_at(insn_addr)) { // movptr + return get_target_of_movptr(insn_addr); -+ } else if (NativeInstruction::is_li64_at(insn_addr)) { // li64 -+ return get_target_of_li64(insn_addr); + } else if (NativeInstruction::is_li32_at(insn_addr)) { // li32 + return get_target_of_li32(insn_addr); + } else { @@ -23884,7 +20241,7 @@ index 00000000000..86710295444 + // instruction. + if (NativeInstruction::is_li32_at(insn_addr)) { + // Move narrow OOP -+ uint32_t n = CompressedOops::narrow_oop_value(cast_to_oop(o)); ++ narrowOop n = CompressedOops::encode((oop)o); + return patch_imm_in_li32(insn_addr, (int32_t)n); + } else if (NativeInstruction::is_movptr_at(insn_addr)) { + // Move wide OOP @@ -23897,10 +20254,10 @@ index 00000000000..86710295444 +void MacroAssembler::reinit_heapbase() { + if (UseCompressedOops) { + if (Universe::is_fully_initialized()) { -+ mv(xheapbase, CompressedOops::ptrs_base()); ++ mv(xheapbase, Universe::narrow_ptrs_base()); + } else { + int32_t offset = 0; -+ la_patchable(xheapbase, ExternalAddress((address)CompressedOops::ptrs_base_addr()), offset); ++ la_patchable(xheapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()), offset); + ld(xheapbase, Address(xheapbase, offset)); + } + } @@ -23908,16 +20265,10 @@ index 00000000000..86710295444 + +void MacroAssembler::mv(Register Rd, Address dest) { + assert(dest.getMode() == Address::literal, "Address mode should be Address::literal"); -+ code_section()->relocate(pc(), dest.rspec()); ++ relocate(dest.rspec()); + movptr(Rd, dest.target()); +} + -+void MacroAssembler::mv(Register Rd, address addr) { -+ // Here in case of use with relocation, use fix length instruciton -+ // movptr instead of li -+ movptr(Rd, addr); -+} -+ +void MacroAssembler::mv(Register Rd, RegisterOrConstant src) { + if (src.is_register()) { + mv(Rd, src.as_register()); @@ -23995,7 +20346,7 @@ index 00000000000..86710295444 +// reverse bytes in halfword in lower 16 bits and sign-extend +// Rd[15:0] = Rs[7:0] Rs[15:8] (sign-extend to 64 bits) +void MacroAssembler::revb_h_h(Register Rd, Register Rs, Register tmp) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + srai(Rd, Rd, 48); + return; @@ -24012,7 +20363,7 @@ index 00000000000..86710295444 +// reverse bytes in lower word and sign-extend +// Rd[31:0] = Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] (sign-extend to 64 bits) +void MacroAssembler::revb_w_w(Register Rd, Register Rs, Register tmp1, Register tmp2) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + srai(Rd, Rd, 32); + return; @@ -24029,7 +20380,7 @@ index 00000000000..86710295444 +// reverse bytes in halfword in lower 16 bits and zero-extend +// Rd[15:0] = Rs[7:0] Rs[15:8] (zero-extend to 64 bits) +void MacroAssembler::revb_h_h_u(Register Rd, Register Rs, Register tmp) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + srli(Rd, Rd, 48); + return; @@ -24046,11 +20397,11 @@ index 00000000000..86710295444 +// reverse bytes in halfwords in lower 32 bits and zero-extend +// Rd[31:0] = Rs[23:16] Rs[31:24] Rs[7:0] Rs[15:8] (zero-extend to 64 bits) +void MacroAssembler::revb_h_w_u(Register Rd, Register Rs, Register tmp1, Register tmp2) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + rori(Rd, Rd, 32); + roriw(Rd, Rd, 16); -+ zext_w(Rd, Rd); ++ zero_extend(Rd, Rd, 32); + return; + } + assert_different_registers(Rs, tmp1, tmp2); @@ -24079,16 +20430,16 @@ index 00000000000..86710295444 +// reverse bytes in each halfword +// Rd[63:0] = Rs[55:48] Rs[63:56] Rs[39:32] Rs[47:40] Rs[23:16] Rs[31:24] Rs[7:0] Rs[15:8] +void MacroAssembler::revb_h(Register Rd, Register Rs, Register tmp1, Register tmp2) { -+ if (UseRVB) { ++ if (UseZbb) { + assert_different_registers(Rs, tmp1); + assert_different_registers(Rd, tmp1); + rev8(Rd, Rs); -+ zext_w(tmp1, Rd); ++ zero_extend(tmp1, Rd, 32); + roriw(tmp1, tmp1, 16); + slli(tmp1, tmp1, 32); + srli(Rd, Rd, 32); + roriw(Rd, Rd, 16); -+ zext_w(Rd, Rd); ++ zero_extend(Rd, Rd, 32); + orr(Rd, Rd, tmp1); + return; + } @@ -24103,7 +20454,7 @@ index 00000000000..86710295444 +// reverse bytes in each word +// Rd[63:0] = Rs[39:32] Rs[47:40] Rs[55:48] Rs[63:56] Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] +void MacroAssembler::revb_w(Register Rd, Register Rs, Register tmp1, Register tmp2) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + rori(Rd, Rd, 32); + return; @@ -24117,7 +20468,7 @@ index 00000000000..86710295444 +// reverse bytes in doubleword +// Rd[63:0] = Rs[7:0] Rs[15:8] Rs[23:16] Rs[31:24] Rs[39:32] Rs[47,40] Rs[55,48] Rs[63:56] +void MacroAssembler::revb(Register Rd, Register Rs, Register tmp1, Register tmp2) { -+ if (UseRVB) { ++ if (UseZbb) { + rev8(Rd, Rs); + return; + } @@ -24139,7 +20490,7 @@ index 00000000000..86710295444 +// rotate right with shift bits +void MacroAssembler::ror_imm(Register dst, Register src, uint32_t shift, Register tmp) +{ -+ if (UseRVB) { ++ if (UseZbb) { + rori(dst, src, shift); + return; + } @@ -24157,7 +20508,7 @@ index 00000000000..86710295444 + and_imm12(Rd, Rn, imm); + } else { + assert_different_registers(Rn, tmp); -+ li(tmp, imm); ++ mv(tmp, imm); + andr(Rd, Rn, tmp); + } +} @@ -24171,7 +20522,7 @@ index 00000000000..86710295444 + ori(tmp1, tmp1, src.as_constant()); + } else { + assert_different_registers(tmp1, tmp2); -+ li(tmp2, src.as_constant()); ++ mv(tmp2, src.as_constant()); + orr(tmp1, tmp1, tmp2); + } + } @@ -24181,8 +20532,8 @@ index 00000000000..86710295444 +void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp, Label &L) { + if (UseCompressedClassPointers) { + lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); -+ if (CompressedKlassPointers::base() == NULL) { -+ slli(tmp, tmp, CompressedKlassPointers::shift()); ++ if (Universe::narrow_klass_base() == NULL) { ++ slli(tmp, tmp, Universe::narrow_klass_shift()); + beq(trial_klass, tmp, L); + return; + } @@ -24193,10 +20544,10 @@ index 00000000000..86710295444 + beq(trial_klass, tmp, L); +} + -+// Move an oop into a register. immediate is true if we want -+// immediate instructions and nmethod entry barriers are not enabled. -+// i.e. we are not going to patch this instruction while the code is being -+// executed by another thread. ++// Move an oop into a register. immediate is true if we want ++// immediate instructions, i.e. we are not going to patch this ++// instruction while the code is being executed by another thread. In ++// that case we can use move immediates rather than the constant pool. +void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) { + int oop_index; + if (obj == NULL) { @@ -24205,17 +20556,13 @@ index 00000000000..86710295444 +#ifdef ASSERT + { + ThreadInVMfromUnknown tiv; -+ assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); ++ assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "should be real oop"); + } +#endif + oop_index = oop_recorder()->find_index(obj); + } + RelocationHolder rspec = oop_Relocation::spec(oop_index); -+ -+ // nmethod entry barrier necessitate using the constant pool. They have to be -+ // ordered with respected to oop access. -+ // Using immediate literals would necessitate fence.i. -+ if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate) { ++ if (!immediate) { + address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address + ld_constant(dst, Address(dummy, rspec)); + } else @@ -24255,7 +20602,7 @@ index 00000000000..86710295444 + // was post-decremented.) Skip this address by starting at i=1, and + // touch a few more pages below. N.B. It is important to touch all + // the way down to and including i=StackShadowPages. -+ for (int i = 0; i < (int)(StackOverflow::stack_shadow_zone_size() / os::vm_page_size()) - 1; i++) { ++ for (int i = 0; i < (int)(JavaThread::stack_shadow_zone_size() / os::vm_page_size()) - 1; i++) { + // this could be any sized move but this is can be a debugging crumb + // so the bigger the better. + sub(tmp, tmp, os::vm_page_size()); @@ -24264,7 +20611,6 @@ index 00000000000..86710295444 +} + +SkipIfEqual::SkipIfEqual(MacroAssembler* masm, const bool* flag_addr, bool value) { -+ assert_cond(masm != NULL); + int32_t offset = 0; + _masm = masm; + _masm->la_patchable(t0, ExternalAddress((address)flag_addr), offset); @@ -24273,7 +20619,6 @@ index 00000000000..86710295444 +} + +SkipIfEqual::~SkipIfEqual() { -+ assert_cond(_masm != NULL); + _masm->bind(_label); + _masm = NULL; +} @@ -24293,22 +20638,6 @@ index 00000000000..86710295444 + access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, noreg); +} + -+// ((WeakHandle)result).resolve() -+void MacroAssembler::resolve_weak_handle(Register result, Register tmp) { -+ assert_different_registers(result, tmp); -+ Label resolved; -+ -+ // A null weak handle resolves to null. -+ beqz(result, resolved); -+ -+ // Only 64 bit platforms support GCs that require a tmp register -+ // Only IN_HEAP loads require a thread_tmp register -+ // WeakHandle::resolve is an indirection like jweak. -+ access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, -+ result, Address(result), tmp, noreg /* tmp_thread */); -+ bind(resolved); -+} -+ +void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, + Register dst, Address src, + Register tmp1, Register thread_tmp) { @@ -24350,9 +20679,9 @@ index 00000000000..86710295444 +// Algorithm must match CompressedOops::encode. +void MacroAssembler::encode_heap_oop(Register d, Register s) { + verify_oop(s, "broken oop in encode_heap_oop"); -+ if (CompressedOops::base() == NULL) { -+ if (CompressedOops::shift() != 0) { -+ assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); ++ if (Universe::narrow_oop_base() == NULL) { ++ if (Universe::narrow_oop_shift() != 0) { ++ assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + srli(d, s, LogMinObjAlignmentInBytes); + } else { + mv(d, s); @@ -24363,9 +20692,9 @@ index 00000000000..86710295444 + bgez(d, notNull); + mv(d, zr); + bind(notNull); -+ if (CompressedOops::shift() != 0) { -+ assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); -+ srli(d, d, CompressedOops::shift()); ++ if (Universe::narrow_oop_shift() != 0) { ++ assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); ++ srli(d, d, Universe::narrow_oop_shift()); + } + } +} @@ -24404,9 +20733,9 @@ index 00000000000..86710295444 +void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) { + assert(UseCompressedClassPointers, "should only be used for compressed headers"); + -+ if (CompressedKlassPointers::base() == NULL) { -+ if (CompressedKlassPointers::shift() != 0) { -+ assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); ++ if (Universe::narrow_klass_base() == NULL) { ++ if (Universe::narrow_klass_shift() != 0) { ++ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + slli(dst, src, LogKlassAlignmentInBytes); + } else { + mv(dst, src); @@ -24420,10 +20749,10 @@ index 00000000000..86710295444 + } + + assert_different_registers(src, xbase); -+ li(xbase, (uintptr_t)CompressedKlassPointers::base()); ++ mv(xbase, (uintptr_t)Universe::narrow_klass_base()); + -+ if (CompressedKlassPointers::shift() != 0) { -+ assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); ++ if (Universe::narrow_klass_shift() != 0) { ++ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + assert_different_registers(t0, xbase); + shadd(dst, src, xbase, t0, LogKlassAlignmentInBytes); + } else { @@ -24440,9 +20769,9 @@ index 00000000000..86710295444 +void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) { + assert(UseCompressedClassPointers, "should only be used for compressed headers"); + -+ if (CompressedKlassPointers::base() == NULL) { -+ if (CompressedKlassPointers::shift() != 0) { -+ assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); ++ if (Universe::narrow_klass_base() == NULL) { ++ if (Universe::narrow_klass_shift() != 0) { ++ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + srli(dst, src, LogKlassAlignmentInBytes); + } else { + mv(dst, src); @@ -24450,8 +20779,8 @@ index 00000000000..86710295444 + return; + } + -+ if (((uint64_t)(uintptr_t)CompressedKlassPointers::base() & 0xffffffff) == 0 && -+ CompressedKlassPointers::shift() == 0) { ++ if (((uint64_t)(uintptr_t)Universe::narrow_klass_base() & 0xffffffff) == 0 && ++ Universe::narrow_klass_shift() == 0) { + zero_extend(dst, src, 32); + return; + } @@ -24462,10 +20791,10 @@ index 00000000000..86710295444 + } + + assert_different_registers(src, xbase); -+ li(xbase, (intptr_t)CompressedKlassPointers::base()); ++ mv(xbase, (intptr_t)Universe::narrow_klass_base()); + sub(dst, src, xbase); -+ if (CompressedKlassPointers::shift() != 0) { -+ assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); ++ if (Universe::narrow_klass_shift() != 0) { ++ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); + srli(dst, dst, LogKlassAlignmentInBytes); + } + if (xbase == xheapbase) { @@ -24483,22 +20812,22 @@ index 00000000000..86710295444 + // Cannot assert, unverified entry point counts instructions (see .ad file) + // vtableStubs also counts instructions in pd_code_size_limit. + // Also do not verify_oop as this is called by verify_oop. -+ if (CompressedOops::shift() != 0) { -+ assert(LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); ++ if (Universe::narrow_oop_shift() != 0) { ++ assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); + slli(dst, src, LogMinObjAlignmentInBytes); -+ if (CompressedOops::base() != NULL) { ++ if (Universe::narrow_oop_base() != NULL) { + add(dst, xheapbase, dst); + } + } else { -+ assert(CompressedOops::base() == NULL, "sanity"); ++ assert(Universe::narrow_oop_base() == NULL, "sanity"); + mv(dst, src); + } +} + +void MacroAssembler::decode_heap_oop(Register d, Register s) { -+ if (CompressedOops::base() == NULL) { -+ if (CompressedOops::shift() != 0 || d != s) { -+ slli(d, s, CompressedOops::shift()); ++ if (Universe::narrow_oop_base() == NULL) { ++ if (Universe::narrow_oop_shift() != 0 || d != s) { ++ slli(d, s, Universe::narrow_oop_shift()); + } + } else { + Label done; @@ -24615,7 +20944,7 @@ index 00000000000..86710295444 + if (itable_index.is_register()) { + slli(t0, itable_index.as_register(), 3); + } else { -+ li(t0, itable_index.as_constant() << 3); ++ mv(t0, itable_index.as_constant() << 3); + } + add(recv_klass, recv_klass, t0); + if (itentry_off) { @@ -24710,16 +21039,17 @@ index 00000000000..86710295444 + bind(L_failure); +} + -+void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod) { -+ ld(t0, Address(xthread, JavaThread::polling_word_offset())); -+ if (acquire) { -+ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); -+ } -+ if (at_return) { -+ bgtu(in_nmethod ? sp : fp, t0, slow_path, true /* is_far */); ++void MacroAssembler::safepoint_poll(Label& slow_path) { ++ if (SafepointMechanism::uses_thread_local_poll()) { ++ ld(t1, Address(xthread, Thread::polling_page_offset())); ++ andi(t0, t1, SafepointMechanism::poll_bit()); ++ bnez(t0, slow_path); + } else { -+ andi(t0, t0, SafepointMechanism::poll_bit()); -+ bnez(t0, slow_path, true /* is_far */); ++ int32_t offset = 0; ++ la_patchable(t0, ExternalAddress(SafepointSynchronize::address_of_state()), offset); ++ lwu(t0, Address(t0, offset)); ++ assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code"); ++ bnez(t0, slow_path); + } +} + @@ -24805,10 +21135,10 @@ index 00000000000..86710295444 + andi(aligned_addr, addr, ~3); + + if (size == int8) { -+ addi(mask, zr, 0xff); ++ mv(mask, 0xff); + } else { + // size == int16 case -+ addi(mask, zr, -1); ++ mv(mask, -1); + zero_extend(mask, mask, 16); + } + sll(mask, mask, shift); @@ -24848,7 +21178,7 @@ index 00000000000..86710295444 + bnez(tmp, retry); + + if (result_as_bool) { -+ addi(result, zr, 1); ++ mv(result, 1); + j(done); + + bind(fail); @@ -24883,7 +21213,7 @@ index 00000000000..86710295444 + assert_different_registers(addr, old, mask, not_mask, new_val, expected, shift, tmp); + cmpxchg_narrow_value_helper(addr, expected, new_val, size, tmp1, tmp2, tmp3); + -+ Label succ, fail, done; ++ Label fail, done; + + lr_w(old, aligned_addr, acquire); + andr(tmp, old, mask); @@ -24892,13 +21222,14 @@ index 00000000000..86710295444 + andr(tmp, old, not_mask); + orr(tmp, tmp, new_val); + sc_w(tmp, tmp, aligned_addr, release); -+ beqz(tmp, succ); ++ bnez(tmp, fail); + -+ bind(fail); -+ addi(result, zr, 1); ++ // Success ++ mv(result, 1); + j(done); + -+ bind(succ); ++ // Fail ++ bind(fail); + mv(result, zr); + + bind(done); @@ -24920,7 +21251,7 @@ index 00000000000..86710295444 + + // equal, succeed + if (result_as_bool) { -+ li(result, 1); ++ mv(result, 1); + } else { + mv(result, expected); + } @@ -24942,20 +21273,20 @@ index 00000000000..86710295444 + enum operand_size size, + Assembler::Aqrl acquire, Assembler::Aqrl release, + Register result) { -+ Label fail, done, sc_done; ++ Label fail, done; + load_reserved(addr, size, acquire); + bne(t0, expected, fail); + store_conditional(addr, new_val, size, release); -+ beqz(t0, sc_done); ++ bnez(t0, fail); + -+ // fail -+ bind(fail); -+ li(result, 1); ++ // Success ++ mv(result, 1); + j(done); + -+ // sc_done -+ bind(sc_done); -+ mv(result, 0); ++ // Fail ++ bind(fail); ++ mv(result, zr); ++ + bind(done); +} + @@ -25197,7 +21528,7 @@ index 00000000000..86710295444 + add(x15, x15, Array::base_offset_in_bytes()); + + // Set t0 to an obvious invalid value, falling through by default -+ li(t0, -1); ++ mv(t0, -1); + // Scan X12 words at [X15] for an occurrence of X10. + repne_scan(x15, x10, x12, t0); + @@ -25254,11 +21585,10 @@ index 00000000000..86710295444 + RegSet::range(x28, x31) + ra - thread; + push_reg(saved_regs, sp); + -+ int32_t offset = 0; -+ movptr_with_offset(ra, CAST_FROM_FN_PTR(address, Thread::current), offset); -+ jalr(ra, ra, offset); -+ if (thread != x10) { -+ mv(thread, x10); ++ mv(ra, CAST_FROM_FN_PTR(address, Thread::current)); ++ jalr(ra); ++ if (thread != c_rarg0) { ++ mv(thread, c_rarg0); + } + + // restore pushed registers @@ -25266,9 +21596,9 @@ index 00000000000..86710295444 +} + +void MacroAssembler::load_byte_map_base(Register reg) { -+ CardTable::CardValue* byte_map_base = ++ jbyte *byte_map_base = + ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base(); -+ li(reg, (uint64_t)byte_map_base); ++ mv(reg, (uint64_t)byte_map_base); +} + +void MacroAssembler::la_patchable(Register reg1, const Address &dest, int32_t &offset) { @@ -25282,8 +21612,7 @@ index 00000000000..86710295444 + assert(is_valid_riscv64_address(dest.target()), "bad address"); + assert(dest.getMode() == Address::literal, "la_patchable must be applied to a literal address"); + -+ InstructionMark im(this); -+ code_section()->relocate(inst_mark(), dest.rspec()); ++ relocate(dest.rspec()); + // RISC-V doesn't compute a page-aligned address, in order to partially + // compensate for the use of *signed* offsets in its base+disp12 + // addressing mode (RISC-V's PC-relative reach remains asymmetric @@ -25304,7 +21633,6 @@ index 00000000000..86710295444 + sd(fp, Address(sp, framesize - 2 * wordSize)); + sd(ra, Address(sp, framesize - wordSize)); + if (PreserveFramePointer) { add(fp, sp, framesize); } -+ verify_cross_modify_fence_not_required(); +} + +void MacroAssembler::remove_frame(int framesize) { @@ -25340,23 +21668,246 @@ index 00000000000..86710295444 + bind(no_reserved_zone_enabling); +} + ++void MacroAssembler::atomic_incw(Register counter_addr, Register tmp) { ++ Label retry_load; ++ bind(retry_load); ++ // flush and load exclusive from the memory location ++ lr_w(tmp, counter_addr); ++ addw(tmp, tmp, 1); ++ // if we store+flush with no intervening write tmp wil be zero ++ sc_w(tmp, tmp, counter_addr); ++ bnez(tmp, retry_load); ++} ++ ++void MacroAssembler::load_prototype_header(Register dst, Register src) { ++ load_klass(dst, src); ++ ld(dst, Address(dst, Klass::prototype_header_offset())); ++} ++ ++int MacroAssembler::biased_locking_enter(Register lock_reg, ++ Register obj_reg, ++ Register swap_reg, ++ Register tmp_reg, ++ bool swap_reg_contains_mark, ++ Label& done, ++ Label* slow_case, ++ BiasedLockingCounters* counters, ++ Register flag) { ++ assert(UseBiasedLocking, "why call this otherwise?"); ++ assert_different_registers(lock_reg, obj_reg, swap_reg); ++ ++ if (PrintBiasedLockingStatistics && counters == NULL) ++ counters = BiasedLocking::counters(); ++ ++ assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg, t0); ++ assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); ++ Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); ++ ++ // Biased locking ++ // See whether the lock is currently biased toward our thread and ++ // whether the epoch is still valid ++ // Note that the runtime guarantees sufficient alignment of JavaThread ++ // pointers to allow age to be placed into low bits ++ // First check to see whether biasing is even enabled for this object ++ Label cas_label; ++ int null_check_offset = -1; ++ if (!swap_reg_contains_mark) { ++ null_check_offset = offset(); ++ ld(swap_reg, mark_addr); ++ } ++ andi(tmp_reg, swap_reg, markOopDesc::biased_lock_mask_in_place); ++ li(t0, markOopDesc::biased_lock_pattern); ++ bne(t0, tmp_reg, cas_label); ++ // The bias pattern is present in the object's header. Need to check ++ // whether the bias owner and the epoch are both still current. ++ load_prototype_header(tmp_reg, obj_reg); ++ orr(tmp_reg, tmp_reg, xthread); ++ xorr(tmp_reg, swap_reg, tmp_reg); ++ andi(tmp_reg, tmp_reg, ~((int) markOopDesc::age_mask_in_place)); ++ if (flag->is_valid()) { ++ mv(flag, tmp_reg); ++ } ++ if (counters != NULL) { ++ Label around; ++ bnez(tmp_reg, around); ++ atomic_incw(Address((address)counters->biased_lock_entry_count_addr()), tmp_reg, t0); ++ j(done); ++ bind(around); ++ } else { ++ beqz(tmp_reg, done); ++ } ++ ++ Label try_revoke_bias; ++ Label try_rebias; ++ ++ // At this point we know that the header has the bias pattern and ++ // that we are not the bias owner in the current epoch. We need to ++ // figure out more details about the state of the header in order to ++ // know what operations can be legally performed on the object's ++ // header. ++ ++ // If the low three bits in the xor result aren't clear, that means ++ // the prototype header is no longer biased and we have to revoke ++ // the bias on this object. ++ andi(t0, tmp_reg, markOopDesc::biased_lock_mask_in_place); ++ bnez(t0, try_revoke_bias); ++ ++ // Biasing is still enabled for this data type. See whether the ++ // epoch of the current bias is still valid, meaning that the epoch ++ // bits of the mark word are equal to the epoch bits of the ++ // prototype header. (Note that the prototype header's epoch bits ++ // only change at a safepoint.) If not, attempt to rebias the object ++ // toward the current thread. Note that we must be absolutely sure ++ // that the current epoch is invalid in order to do this because ++ // otherwise the manipulations it performs on the mark word are ++ // illegal. ++ andi(t0, tmp_reg, markOopDesc::epoch_mask_in_place); ++ bnez(t0, try_rebias); ++ ++ // The epoch of the current bias is still valid but we know nothing ++ // about the owner; it might be set or it might be clear. Try to ++ // acquire the bias of the object using an atomic operation. If this ++ // fails we will go in to the runtime to revoke the object's bias. ++ // Note that we first construct the presumed unbiased header so we ++ // don't accidentally blow away another thread's valid bias. ++ { ++ Label cas_success; ++ Label counter; ++ mv(t0, markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); ++ andr(swap_reg, swap_reg, t0); ++ orr(tmp_reg, swap_reg, xthread); ++ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, slow_case); ++ // cas failed here if slow_cass == NULL ++ if (flag->is_valid()) { ++ mv(flag, 1); ++ j(counter); ++ } ++ // If the biasing toward our thread failed, this means that ++ // another thread succeeded in biasing it toward itself and we ++ // need to revoke that bias. The revocation will occur in the ++ // interpreter runtime in the slow case. ++ bind(cas_success); ++ if (flag->is_valid()) { ++ mv(flag, 0); ++ bind(counter); ++ } ++ if (counters != NULL) { ++ atomic_incw(Address((address)counters->anonymously_biased_lock_entry_count_addr()), ++ tmp_reg, t0); ++ } ++ } ++ j(done); ++ ++ bind(try_rebias); ++ // At this point we know the epoch has expired, meaning that the ++ // current "bias owner", if any, is actually invalid. Under these ++ // circumstances _only_, we are allowed to use the current header's ++ // value as the comparison value when doing the cas to acquire the ++ // bias in the current epoch. In other words, we allow transfer of ++ // the bias from one thread to another directly in this situation. ++ // ++ // FIXME: due to a lack of registers we currently blow away the age ++ // bits in this situation. Should attempt to preserve them. ++ { ++ Label cas_success; ++ Label counter; ++ load_prototype_header(tmp_reg, obj_reg); ++ orr(tmp_reg, xthread, tmp_reg); ++ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, slow_case); ++ // cas failed here if slow_cass == NULL ++ if (flag->is_valid()) { ++ mv(flag, 1); ++ j(counter); ++ } ++ ++ // If the biasing toward our thread failed, then another thread ++ // succeeded in biasing it toward itself and we need to revoke that ++ // bias. The revocation will occur in the runtime in the slow case. ++ bind(cas_success); ++ if (flag->is_valid()) { ++ mv(flag, 0); ++ bind(counter); ++ } ++ if (counters != NULL) { ++ atomic_incw(Address((address)counters->rebiased_lock_entry_count_addr()), ++ tmp_reg, t0); ++ } ++ } ++ j(done); ++ ++ bind(try_revoke_bias); ++ // The prototype mark in the klass doesn't have the bias bit set any ++ // more, indicating that objects of this data type are not supposed ++ // to be biased any more. We are going to try to reset the mark of ++ // this object to the prototype value and fall through to the ++ // CAS-based locking scheme. Note that if our CAS fails, it means ++ // that another thread raced us for the privilege of revoking the ++ // bias of this particular object, so it's okay to continue in the ++ // normal locking code. ++ // ++ // FIXME: due to a lack of registers we currently blow away the age ++ // bits in this situation. Should attempt to preserve them. ++ { ++ Label cas_success, nope; ++ load_prototype_header(tmp_reg, obj_reg); ++ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, &nope); ++ bind(cas_success); ++ ++ // Fall through to the normal CAS-based lock, because no matter what ++ // the result of the above CAS, some thread must have succeeded in ++ // removing the bias bit from the object's header. ++ if (counters != NULL) { ++ atomic_incw(Address((address)counters->revoked_lock_entry_count_addr()), tmp_reg, ++ t0); ++ } ++ bind(nope); ++ } ++ ++ bind(cas_label); ++ ++ return null_check_offset; ++} ++ ++void MacroAssembler::biased_locking_exit(Register obj_reg, Register tmp_reg, Label& done, Register flag) { ++ assert(UseBiasedLocking, "why call this otherwise?"); ++ ++ // Check for biased locking unlock case, which is a no-op ++ // Note: we do not have to check the thread ID for two reasons. ++ // First, the interpreter checks for IllegalMonitorStateException at ++ // a higher level. Second, if the bias was revoked while we held the ++ // lock, the object could not be rebiased toward another thread, so ++ // the bias bit would be clear. ++ ld(tmp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); ++ andi(tmp_reg, tmp_reg, markOopDesc::biased_lock_mask_in_place); ++ sub(tmp_reg, tmp_reg, markOopDesc::biased_lock_pattern); ++ if (flag->is_valid()) { mv(flag, tmp_reg); } ++ beqz(tmp_reg, done); ++} ++ +// Move the address of the polling page into dest. -+void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype) { -+ ld(dest, Address(xthread, JavaThread::polling_page_offset())); ++void MacroAssembler::get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype) { ++ if (SafepointMechanism::uses_thread_local_poll()) { ++ ld(dest, Address(xthread, Thread::polling_page_offset())); ++ } else { ++ uint64_t align = (uint64_t)page & 0xfff; ++ assert(align == 0, "polling page must be page aligned"); ++ la_patchable(dest, Address(page, rtype), offset); ++ } +} + +// Read the polling page. The address of the polling page must +// already be in r. -+address MacroAssembler::read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype) { -+ address mark; -+ { -+ InstructionMark im(this); -+ code_section()->relocate(inst_mark(), rtype); -+ lwu(zr, Address(r, offset)); -+ mark = inst_mark(); -+ } -+ verify_cross_modify_fence_not_required(); -+ return mark; ++void MacroAssembler::read_polling_page(Register dest, address page, relocInfo::relocType rtype) { ++ int32_t offset = 0; ++ get_polling_page(dest, page, offset, rtype); ++ read_polling_page(dest, offset, rtype); ++} ++ ++// Read the polling page. The address of the polling page must ++// already be in r. ++void MacroAssembler::read_polling_page(Register dest, int32_t offset, relocInfo::relocType rtype) { ++ relocate(rtype); ++ lwu(zr, Address(dest, offset)); +} + +void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { @@ -25366,13 +21917,11 @@ index 00000000000..86710295444 + assert (UseCompressedOops, "should only be used for compressed oops"); + assert (Universe::heap() != NULL, "java heap should be initialized"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); -+ assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); ++ assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "should be real oop"); + } +#endif + int oop_index = oop_recorder()->find_index(obj); -+ InstructionMark im(this); -+ RelocationHolder rspec = oop_Relocation::spec(oop_index); -+ code_section()->relocate(inst_mark(), rspec); ++ relocate(oop_Relocation::spec(oop_index)); + li32(dst, 0xDEADBEEF); + zero_extend(dst, dst, 32); +} @@ -25381,12 +21930,10 @@ index 00000000000..86710295444 + assert (UseCompressedClassPointers, "should only be used for compressed headers"); + assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); + int index = oop_recorder()->find_index(k); -+ assert(!Universe::heap()->is_in(k), "should not be an oop"); ++ assert(!Universe::heap()->is_in_reserved(k), "should not be an oop"); + -+ InstructionMark im(this); -+ RelocationHolder rspec = metadata_Relocation::spec(index); -+ code_section()->relocate(inst_mark(), rspec); -+ narrowKlass nk = CompressedKlassPointers::encode(k); ++ narrowKlass nk = Klass::encode_klass(k); ++ relocate(metadata_Relocation::spec(index)); + li32(dst, nk); + zero_extend(dst, dst, 32); +} @@ -25409,7 +21956,7 @@ index 00000000000..86710295444 + CompileTask* task = ciEnv::current()->task(); + in_scratch_emit_size = + (task != NULL && is_c2_compile(task->comp_level()) && -+ Compile::current()->output()->in_scratch_emit_size()); ++ Compile::current()->in_scratch_emit_size()); +#endif + if (!in_scratch_emit_size) { + address stub = emit_trampoline_stub(offset(), entry.target()); @@ -25421,6 +21968,11 @@ index 00000000000..86710295444 + } + + if (cbuf != NULL) { cbuf->set_insts_mark(); } ++#ifdef ASSERT ++ if (entry.rspec().type() != relocInfo::runtime_call_type) { ++ assert_alignment(pc()); ++ } ++#endif + relocate(entry.rspec()); + if (!far_branches()) { + jal(entry.target()); @@ -25503,19 +22055,47 @@ index 00000000000..86710295444 + } +} + -+void MacroAssembler::add_memory_int64(const Address dst, int64_t imm) { ++void MacroAssembler::increment(const Address dst, int64_t value) { ++ assert(((dst.getMode() == Address::base_plus_offset && ++ is_offset_in_range(dst.offset(), 12)) || is_imm_in_range(value, 12, 0)), ++ "invalid value and address mode combination"); + Address adr = add_memory_helper(dst); -+ assert_different_registers(adr.base(), t0); ++ assert(!adr.uses(t0), "invalid dst for address increment"); + ld(t0, adr); -+ addi(t0, t0, imm); ++ add(t0, t0, value, t1); + sd(t0, adr); +} + -+void MacroAssembler::add_memory_int32(const Address dst, int32_t imm) { ++void MacroAssembler::incrementw(const Address dst, int32_t value) { ++ assert(((dst.getMode() == Address::base_plus_offset && ++ is_offset_in_range(dst.offset(), 12)) || is_imm_in_range(value, 12, 0)), ++ "invalid value and address mode combination"); + Address adr = add_memory_helper(dst); -+ assert_different_registers(adr.base(), t0); ++ assert(!adr.uses(t0), "invalid dst for address increment"); + lwu(t0, adr); -+ addiw(t0, t0, imm); ++ addw(t0, t0, value, t1); ++ sw(t0, adr); ++} ++ ++void MacroAssembler::decrement(const Address dst, int64_t value) { ++ assert(((dst.getMode() == Address::base_plus_offset && ++ is_offset_in_range(dst.offset(), 12)) || is_imm_in_range(value, 12, 0)), ++ "invalid value and address mode combination"); ++ Address adr = add_memory_helper(dst); ++ assert(!adr.uses(t0), "invalid dst for address decrement"); ++ ld(t0, adr); ++ sub(t0, t0, value, t1); ++ sd(t0, adr); ++} ++ ++void MacroAssembler::decrementw(const Address dst, int32_t value) { ++ assert(((dst.getMode() == Address::base_plus_offset && ++ is_offset_in_range(dst.offset(), 12)) || is_imm_in_range(value, 12, 0)), ++ "invalid value and address mode combination"); ++ Address adr = add_memory_helper(dst); ++ assert(!adr.uses(t0), "invalid dst for address decrement"); ++ lwu(t0, adr); ++ subw(t0, t0, value, t1); + sw(t0, adr); +} + @@ -25527,17 +22107,6 @@ index 00000000000..86710295444 + beq(src1, t0, equal); +} + -+void MacroAssembler::load_method_holder_cld(Register result, Register method) { -+ load_method_holder(result, method); -+ ld(result, Address(result, InstanceKlass::class_loader_data_offset())); -+} -+ -+void MacroAssembler::load_method_holder(Register holder, Register method) { -+ ld(holder, Address(method, Method::const_offset())); // ConstMethod* -+ ld(holder, Address(holder, ConstMethod::constants_offset())); // ConstantPool* -+ ld(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass* -+} -+ +// string indexof +// compute index by trailing zeros +void MacroAssembler::compute_index(Register haystack, Register trailing_zeros, @@ -25606,7 +22175,7 @@ index 00000000000..86710295444 + add(in, in, t0); + + const int unroll = 8; -+ li(tmp, unroll); ++ mv(tmp, unroll); + blt(len, tmp, L_tail_loop); + bind(L_unroll); + for (int i = 0; i < unroll; i++) { @@ -26085,7 +22654,7 @@ index 00000000000..86710295444 +// shift 16 bits once. +void MacroAssembler::ctzc_bit(Register Rd, Register Rs, bool isLL, Register tmp1, Register tmp2) +{ -+ if (UseRVB) { ++ if (UseZbb) { + assert_different_registers(Rd, Rs, tmp1); + int step = isLL ? 8 : 16; + ctz(Rd, Rs); @@ -26096,7 +22665,7 @@ index 00000000000..86710295444 + assert_different_registers(Rd, Rs, tmp1, tmp2); + Label Loop; + int step = isLL ? 8 : 16; -+ li(Rd, -step); ++ mv(Rd, -step); + mv(tmp2, Rs); + + bind(Loop); @@ -26113,7 +22682,7 @@ index 00000000000..86710295444 +void MacroAssembler::inflate_lo32(Register Rd, Register Rs, Register tmp1, Register tmp2) +{ + assert_different_registers(Rd, Rs, tmp1, tmp2); -+ li(tmp1, 0xFF); ++ mv(tmp1, 0xFF); + mv(Rd, zr); + for (int i = 0; i <= 3; i++) + { @@ -26135,7 +22704,7 @@ index 00000000000..86710295444 +void MacroAssembler::inflate_hi32(Register Rd, Register Rs, Register tmp1, Register tmp2) +{ + assert_different_registers(Rd, Rs, tmp1, tmp2); -+ li(tmp1, 0xFF00000000); ++ mv(tmp1, 0xFF00000000); + mv(Rd, zr); + for (int i = 0; i <= 3; i++) + { @@ -26177,7 +22746,7 @@ index 00000000000..86710295444 + if (StubRoutines::riscv::complete()) { + address tpc = trampoline_call(zero_blocks); + if (tpc == NULL) { -+ DEBUG_ONLY(reset_labels(around)); ++ DEBUG_ONLY(reset_labels1(around)); + postcond(pc() == badAddress); + return NULL; + } @@ -26233,7 +22802,7 @@ index 00000000000..86710295444 + Register cnt_reg = t0; + Register loop_base = t1; + cnt = cnt - remainder; -+ li(cnt_reg, cnt); ++ mv(cnt_reg, cnt); + add(loop_base, base, remainder * wordSize); + bind(loop); + sub(cnt_reg, cnt_reg, unroll); @@ -26427,7 +22996,7 @@ index 00000000000..86710295444 +// shift left by shamt and add +// Rd = (Rs1 << shamt) + Rs2 +void MacroAssembler::shadd(Register Rd, Register Rs1, Register Rs2, Register tmp, int shamt) { -+ if (UseRVB) { ++ if (UseZba) { + if (shamt == 1) { + sh1add(Rd, Rs1, Rs2); + return; @@ -26449,14 +23018,14 @@ index 00000000000..86710295444 +} + +void MacroAssembler::zero_extend(Register dst, Register src, int bits) { -+ if (UseRVB) { -+ if (bits == 16) { -+ zext_h(dst, src); -+ return; -+ } else if (bits == 32) { -+ zext_w(dst, src); -+ return; -+ } ++ if (UseZba && bits == 32) { ++ zext_w(dst, src); ++ return; ++ } ++ ++ if (UseZbb && bits == 16) { ++ zext_h(dst, src); ++ return; + } + + if (bits == 8) { @@ -26468,7 +23037,7 @@ index 00000000000..86710295444 +} + +void MacroAssembler::sign_extend(Register dst, Register src, int bits) { -+ if (UseRVB) { ++ if (UseZbb) { + if (bits == 8) { + sext_b(dst, src); + return; @@ -26514,37 +23083,1294 @@ index 00000000000..86710295444 + bind(done); +} + -+void MacroAssembler::safepoint_ifence() { -+ ifence(); -+#ifndef PRODUCT -+ if (VerifyCrossModifyFence) { -+ // Clear the thread state. -+ sb(zr, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); -+ } -+#endif ++#ifdef COMPILER2 ++// short string ++// StringUTF16.indexOfChar ++// StringLatin1.indexOfChar ++void MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, ++ Register ch, Register result, ++ bool isL) ++{ ++ Register ch1 = t0; ++ Register index = t1; ++ ++ BLOCK_COMMENT("string_indexof_char_short {"); ++ ++ Label LOOP, LOOP1, LOOP4, LOOP8; ++ Label MATCH, MATCH1, MATCH2, MATCH3, ++ MATCH4, MATCH5, MATCH6, MATCH7, NOMATCH; ++ ++ mv(result, -1); ++ mv(index, zr); ++ ++ bind(LOOP); ++ addi(t0, index, 8); ++ ble(t0, cnt1, LOOP8); ++ addi(t0, index, 4); ++ ble(t0, cnt1, LOOP4); ++ j(LOOP1); ++ ++ bind(LOOP8); ++ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); ++ beq(ch, ch1, MATCH); ++ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); ++ beq(ch, ch1, MATCH1); ++ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); ++ beq(ch, ch1, MATCH2); ++ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); ++ beq(ch, ch1, MATCH3); ++ isL ? lbu(ch1, Address(str1, 4)) : lhu(ch1, Address(str1, 8)); ++ beq(ch, ch1, MATCH4); ++ isL ? lbu(ch1, Address(str1, 5)) : lhu(ch1, Address(str1, 10)); ++ beq(ch, ch1, MATCH5); ++ isL ? lbu(ch1, Address(str1, 6)) : lhu(ch1, Address(str1, 12)); ++ beq(ch, ch1, MATCH6); ++ isL ? lbu(ch1, Address(str1, 7)) : lhu(ch1, Address(str1, 14)); ++ beq(ch, ch1, MATCH7); ++ addi(index, index, 8); ++ addi(str1, str1, isL ? 8 : 16); ++ blt(index, cnt1, LOOP); ++ j(NOMATCH); ++ ++ bind(LOOP4); ++ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); ++ beq(ch, ch1, MATCH); ++ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); ++ beq(ch, ch1, MATCH1); ++ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); ++ beq(ch, ch1, MATCH2); ++ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); ++ beq(ch, ch1, MATCH3); ++ addi(index, index, 4); ++ addi(str1, str1, isL ? 4 : 8); ++ bge(index, cnt1, NOMATCH); ++ ++ bind(LOOP1); ++ isL ? lbu(ch1, Address(str1)) : lhu(ch1, Address(str1)); ++ beq(ch, ch1, MATCH); ++ addi(index, index, 1); ++ addi(str1, str1, isL ? 1 : 2); ++ blt(index, cnt1, LOOP1); ++ j(NOMATCH); ++ ++ bind(MATCH1); ++ addi(index, index, 1); ++ j(MATCH); ++ ++ bind(MATCH2); ++ addi(index, index, 2); ++ j(MATCH); ++ ++ bind(MATCH3); ++ addi(index, index, 3); ++ j(MATCH); ++ ++ bind(MATCH4); ++ addi(index, index, 4); ++ j(MATCH); ++ ++ bind(MATCH5); ++ addi(index, index, 5); ++ j(MATCH); ++ ++ bind(MATCH6); ++ addi(index, index, 6); ++ j(MATCH); ++ ++ bind(MATCH7); ++ addi(index, index, 7); ++ ++ bind(MATCH); ++ mv(result, index); ++ bind(NOMATCH); ++ BLOCK_COMMENT("} string_indexof_char_short"); +} + -+#ifndef PRODUCT -+void MacroAssembler::verify_cross_modify_fence_not_required() { -+ if (VerifyCrossModifyFence) { -+ // Check if thread needs a cross modify fence. -+ lbu(t0, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); -+ Label fence_not_required; -+ beqz(t0, fence_not_required); -+ // If it does then fail. -+ la(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure))); -+ mv(c_rarg0, xthread); -+ jalr(t0); -+ bind(fence_not_required); ++// StringUTF16.indexOfChar ++// StringLatin1.indexOfChar ++void MacroAssembler::string_indexof_char(Register str1, Register cnt1, ++ Register ch, Register result, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ bool isL) ++{ ++ Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; ++ Register ch1 = t0; ++ Register orig_cnt = t1; ++ Register mask1 = tmp3; ++ Register mask2 = tmp2; ++ Register match_mask = tmp1; ++ Register trailing_char = tmp4; ++ Register unaligned_elems = tmp4; ++ ++ BLOCK_COMMENT("string_indexof_char {"); ++ beqz(cnt1, NOMATCH); ++ ++ addi(t0, cnt1, isL ? -32 : -16); ++ bgtz(t0, DO_LONG); ++ string_indexof_char_short(str1, cnt1, ch, result, isL); ++ j(DONE); ++ ++ bind(DO_LONG); ++ mv(orig_cnt, cnt1); ++ if (AvoidUnalignedAccesses) { ++ Label ALIGNED; ++ andi(unaligned_elems, str1, 0x7); ++ beqz(unaligned_elems, ALIGNED); ++ sub(unaligned_elems, unaligned_elems, 8); ++ neg(unaligned_elems, unaligned_elems); ++ if (!isL) { ++ srli(unaligned_elems, unaligned_elems, 1); ++ } ++ // do unaligned part per element ++ string_indexof_char_short(str1, unaligned_elems, ch, result, isL); ++ bgez(result, DONE); ++ mv(orig_cnt, cnt1); ++ sub(cnt1, cnt1, unaligned_elems); ++ bind(ALIGNED); ++ } ++ ++ // duplicate ch ++ if (isL) { ++ slli(ch1, ch, 8); ++ orr(ch, ch1, ch); ++ } ++ slli(ch1, ch, 16); ++ orr(ch, ch1, ch); ++ slli(ch1, ch, 32); ++ orr(ch, ch1, ch); ++ ++ if (!isL) { ++ slli(cnt1, cnt1, 1); ++ } ++ ++ uint64_t mask0101 = UCONST64(0x0101010101010101); ++ uint64_t mask0001 = UCONST64(0x0001000100010001); ++ mv(mask1, isL ? mask0101 : mask0001); ++ uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); ++ uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); ++ mv(mask2, isL ? mask7f7f : mask7fff); ++ ++ bind(CH1_LOOP); ++ ld(ch1, Address(str1)); ++ addi(str1, str1, 8); ++ addi(cnt1, cnt1, -8); ++ compute_match_mask(ch1, ch, match_mask, mask1, mask2); ++ bnez(match_mask, HIT); ++ bgtz(cnt1, CH1_LOOP); ++ j(NOMATCH); ++ ++ bind(HIT); ++ ctzc_bit(trailing_char, match_mask, isL, ch1, result); ++ srli(trailing_char, trailing_char, 3); ++ addi(cnt1, cnt1, 8); ++ ble(cnt1, trailing_char, NOMATCH); ++ // match case ++ if (!isL) { ++ srli(cnt1, cnt1, 1); ++ srli(trailing_char, trailing_char, 1); ++ } ++ ++ sub(result, orig_cnt, cnt1); ++ add(result, result, trailing_char); ++ j(DONE); ++ ++ bind(NOMATCH); ++ mv(result, -1); ++ ++ bind(DONE); ++ BLOCK_COMMENT("} string_indexof_char"); ++} ++ ++typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); ++ ++// Search for needle in haystack and return index or -1 ++// x10: result ++// x11: haystack ++// x12: haystack_len ++// x13: needle ++// x14: needle_len ++void MacroAssembler::string_indexof(Register haystack, Register needle, ++ Register haystack_len, Register needle_len, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ Register tmp5, Register tmp6, ++ Register result, int ae) ++{ ++ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); ++ ++ Label LINEARSEARCH, LINEARSTUB, DONE, NOMATCH; ++ ++ Register ch1 = t0; ++ Register ch2 = t1; ++ Register nlen_tmp = tmp1; // needle len tmp ++ Register hlen_tmp = tmp2; // haystack len tmp ++ Register result_tmp = tmp4; ++ ++ bool isLL = ae == StrIntrinsicNode::LL; ++ ++ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; ++ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; ++ int needle_chr_shift = needle_isL ? 0 : 1; ++ int haystack_chr_shift = haystack_isL ? 0 : 1; ++ int needle_chr_size = needle_isL ? 1 : 2; ++ int haystack_chr_size = haystack_isL ? 1 : 2; ++ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : ++ (load_chr_insn)&MacroAssembler::lhu; ++ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : ++ (load_chr_insn)&MacroAssembler::lhu; ++ ++ BLOCK_COMMENT("string_indexof {"); ++ ++ // Note, inline_string_indexOf() generates checks: ++ // if (pattern.count > src.count) return -1; ++ // if (pattern.count == 0) return 0; ++ ++ // We have two strings, a source string in haystack, haystack_len and a pattern string ++ // in needle, needle_len. Find the first occurence of pattern in source or return -1. ++ ++ // For larger pattern and source we use a simplified Boyer Moore algorithm. ++ // With a small pattern and source we use linear scan. ++ ++ // needle_len >=8 && needle_len < 256 && needle_len < haystack_len/4, use bmh algorithm. ++ sub(result_tmp, haystack_len, needle_len); ++ // needle_len < 8, use linear scan ++ sub(t0, needle_len, 8); ++ bltz(t0, LINEARSEARCH); ++ // needle_len >= 256, use linear scan ++ sub(t0, needle_len, 256); ++ bgez(t0, LINEARSTUB); ++ // needle_len >= haystack_len/4, use linear scan ++ srli(t0, haystack_len, 2); ++ bge(needle_len, t0, LINEARSTUB); ++ ++ // Boyer-Moore-Horspool introduction: ++ // The Boyer Moore alogorithm is based on the description here:- ++ // ++ // http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm ++ // ++ // This describes and algorithm with 2 shift rules. The 'Bad Character' rule ++ // and the 'Good Suffix' rule. ++ // ++ // These rules are essentially heuristics for how far we can shift the ++ // pattern along the search string. ++ // ++ // The implementation here uses the 'Bad Character' rule only because of the ++ // complexity of initialisation for the 'Good Suffix' rule. ++ // ++ // This is also known as the Boyer-Moore-Horspool algorithm: ++ // ++ // http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm ++ // ++ // #define ASIZE 256 ++ // ++ // int bm(unsigned char *pattern, int m, unsigned char *src, int n) { ++ // int i, j; ++ // unsigned c; ++ // unsigned char bc[ASIZE]; ++ // ++ // /* Preprocessing */ ++ // for (i = 0; i < ASIZE; ++i) ++ // bc[i] = m; ++ // for (i = 0; i < m - 1; ) { ++ // c = pattern[i]; ++ // ++i; ++ // // c < 256 for Latin1 string, so, no need for branch ++ // #ifdef PATTERN_STRING_IS_LATIN1 ++ // bc[c] = m - i; ++ // #else ++ // if (c < ASIZE) bc[c] = m - i; ++ // #endif ++ // } ++ // ++ // /* Searching */ ++ // j = 0; ++ // while (j <= n - m) { ++ // c = src[i+j]; ++ // if (pattern[m-1] == c) ++ // int k; ++ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); ++ // if (k < 0) return j; ++ // // c < 256 for Latin1 string, so, no need for branch ++ // #ifdef SOURCE_STRING_IS_LATIN1_AND_PATTERN_STRING_IS_LATIN1 ++ // // LL case: (c< 256) always true. Remove branch ++ // j += bc[pattern[j+m-1]]; ++ // #endif ++ // #ifdef SOURCE_STRING_IS_UTF_AND_PATTERN_STRING_IS_UTF ++ // // UU case: need if (c if not. ++ // if (c < ASIZE) ++ // j += bc[pattern[j+m-1]]; ++ // else ++ // j += m ++ // #endif ++ // } ++ // return -1; ++ // } ++ ++ // temp register:t0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, result ++ Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH, ++ BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP; ++ ++ Register haystack_end = haystack_len; ++ Register skipch = tmp2; ++ ++ // pattern length is >=8, so, we can read at least 1 register for cases when ++ // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for ++ // UL case. We'll re-read last character in inner pre-loop code to have ++ // single outer pre-loop load ++ const int firstStep = isLL ? 7 : 3; ++ ++ const int ASIZE = 256; ++ const int STORE_BYTES = 8; // 8 bytes stored per instruction(sd) ++ ++ sub(sp, sp, ASIZE); ++ ++ // init BC offset table with default value: needle_len ++ slli(t0, needle_len, 8); ++ orr(t0, t0, needle_len); // [63...16][needle_len][needle_len] ++ slli(tmp1, t0, 16); ++ orr(t0, tmp1, t0); // [63...32][needle_len][needle_len][needle_len][needle_len] ++ slli(tmp1, t0, 32); ++ orr(tmp5, tmp1, t0); // tmp5: 8 elements [needle_len] ++ ++ mv(ch1, sp); // ch1 is t0 ++ mv(tmp6, ASIZE / STORE_BYTES); // loop iterations ++ ++ bind(BM_INIT_LOOP); ++ // for (i = 0; i < ASIZE; ++i) ++ // bc[i] = m; ++ for (int i = 0; i < 4; i++) { ++ sd(tmp5, Address(ch1, i * wordSize)); ++ } ++ add(ch1, ch1, 32); ++ sub(tmp6, tmp6, 4); ++ bgtz(tmp6, BM_INIT_LOOP); ++ ++ sub(nlen_tmp, needle_len, 1); // m - 1, index of the last element in pattern ++ Register orig_haystack = tmp5; ++ mv(orig_haystack, haystack); ++ // result_tmp = tmp4 ++ shadd(haystack_end, result_tmp, haystack, haystack_end, haystack_chr_shift); ++ sub(ch2, needle_len, 1); // bc offset init value, ch2 is t1 ++ mv(tmp3, needle); ++ ++ // for (i = 0; i < m - 1; ) { ++ // c = pattern[i]; ++ // ++i; ++ // // c < 256 for Latin1 string, so, no need for branch ++ // #ifdef PATTERN_STRING_IS_LATIN1 ++ // bc[c] = m - i; ++ // #else ++ // if (c < ASIZE) bc[c] = m - i; ++ // #endif ++ // } ++ bind(BCLOOP); ++ (this->*needle_load_1chr)(ch1, Address(tmp3), noreg); ++ add(tmp3, tmp3, needle_chr_size); ++ if (!needle_isL) { ++ // ae == StrIntrinsicNode::UU ++ mv(tmp6, ASIZE); ++ bgeu(ch1, tmp6, BCSKIP); ++ } ++ add(tmp4, sp, ch1); ++ sb(ch2, Address(tmp4)); // store skip offset to BC offset table ++ ++ bind(BCSKIP); ++ sub(ch2, ch2, 1); // for next pattern element, skip distance -1 ++ bgtz(ch2, BCLOOP); ++ ++ // tmp6: pattern end, address after needle ++ shadd(tmp6, needle_len, needle, tmp6, needle_chr_shift); ++ if (needle_isL == haystack_isL) { ++ // load last 8 bytes (8LL/4UU symbols) ++ ld(tmp6, Address(tmp6, -wordSize)); ++ } else { ++ // UL: from UTF-16(source) search Latin1(pattern) ++ lwu(tmp6, Address(tmp6, -wordSize / 2)); // load last 4 bytes(4 symbols) ++ // convert Latin1 to UTF. eg: 0x0000abcd -> 0x0a0b0c0d ++ // We'll have to wait until load completed, but it's still faster than per-character loads+checks ++ srli(tmp3, tmp6, BitsPerByte * (wordSize / 2 - needle_chr_size)); // pattern[m-1], eg:0x0000000a ++ slli(ch2, tmp6, XLEN - 24); ++ srli(ch2, ch2, XLEN - 8); // pattern[m-2], 0x0000000b ++ slli(ch1, tmp6, XLEN - 16); ++ srli(ch1, ch1, XLEN - 8); // pattern[m-3], 0x0000000c ++ andi(tmp6, tmp6, 0xff); // pattern[m-4], 0x0000000d ++ slli(ch2, ch2, 16); ++ orr(ch2, ch2, ch1); // 0x00000b0c ++ slli(result, tmp3, 48); // use result as temp register ++ orr(tmp6, tmp6, result); // 0x0a00000d ++ slli(result, ch2, 16); ++ orr(tmp6, tmp6, result); // UTF-16:0x0a0b0c0d ++ } ++ ++ // i = m - 1; ++ // skipch = j + i; ++ // if (skipch == pattern[m - 1] ++ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); ++ // else ++ // move j with bad char offset table ++ bind(BMLOOPSTR2); ++ // compare pattern to source string backward ++ shadd(result, nlen_tmp, haystack, result, haystack_chr_shift); ++ (this->*haystack_load_1chr)(skipch, Address(result), noreg); ++ sub(nlen_tmp, nlen_tmp, firstStep); // nlen_tmp is positive here, because needle_len >= 8 ++ if (needle_isL == haystack_isL) { ++ // re-init tmp3. It's for free because it's executed in parallel with ++ // load above. Alternative is to initialize it before loop, but it'll ++ // affect performance on in-order systems with 2 or more ld/st pipelines ++ srli(tmp3, tmp6, BitsPerByte * (wordSize - needle_chr_size)); // UU/LL: pattern[m-1] ++ } ++ if (!isLL) { // UU/UL case ++ slli(ch2, nlen_tmp, 1); // offsets in bytes ++ } ++ bne(tmp3, skipch, BMSKIP); // if not equal, skipch is bad char ++ add(result, haystack, isLL ? nlen_tmp : ch2); ++ ld(ch2, Address(result)); // load 8 bytes from source string ++ mv(ch1, tmp6); ++ if (isLL) { ++ j(BMLOOPSTR1_AFTER_LOAD); ++ } else { ++ sub(nlen_tmp, nlen_tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8 ++ j(BMLOOPSTR1_CMP); ++ } ++ ++ bind(BMLOOPSTR1); ++ shadd(ch1, nlen_tmp, needle, ch1, needle_chr_shift); ++ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); ++ shadd(ch2, nlen_tmp, haystack, ch2, haystack_chr_shift); ++ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); ++ ++ bind(BMLOOPSTR1_AFTER_LOAD); ++ sub(nlen_tmp, nlen_tmp, 1); ++ bltz(nlen_tmp, BMLOOPSTR1_LASTCMP); ++ ++ bind(BMLOOPSTR1_CMP); ++ beq(ch1, ch2, BMLOOPSTR1); ++ ++ bind(BMSKIP); ++ if (!isLL) { ++ // if we've met UTF symbol while searching Latin1 pattern, then we can ++ // skip needle_len symbols ++ if (needle_isL != haystack_isL) { ++ mv(result_tmp, needle_len); ++ } else { ++ mv(result_tmp, 1); ++ } ++ mv(t0, ASIZE); ++ bgeu(skipch, t0, BMADV); ++ } ++ add(result_tmp, sp, skipch); ++ lbu(result_tmp, Address(result_tmp)); // load skip offset ++ ++ bind(BMADV); ++ sub(nlen_tmp, needle_len, 1); ++ // move haystack after bad char skip offset ++ shadd(haystack, result_tmp, haystack, result, haystack_chr_shift); ++ ble(haystack, haystack_end, BMLOOPSTR2); ++ add(sp, sp, ASIZE); ++ j(NOMATCH); ++ ++ bind(BMLOOPSTR1_LASTCMP); ++ bne(ch1, ch2, BMSKIP); ++ ++ bind(BMMATCH); ++ sub(result, haystack, orig_haystack); ++ if (!haystack_isL) { ++ srli(result, result, 1); ++ } ++ add(sp, sp, ASIZE); ++ j(DONE); ++ ++ bind(LINEARSTUB); ++ sub(t0, needle_len, 16); // small patterns still should be handled by simple algorithm ++ bltz(t0, LINEARSEARCH); ++ mv(result, zr); ++ RuntimeAddress stub = NULL; ++ if (isLL) { ++ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ll()); ++ assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated"); ++ } else if (needle_isL) { ++ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ul()); ++ assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated"); ++ } else { ++ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); ++ assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); ++ } ++ trampoline_call(stub); ++ j(DONE); ++ ++ bind(NOMATCH); ++ mv(result, -1); ++ j(DONE); ++ ++ bind(LINEARSEARCH); ++ string_indexof_linearscan(haystack, needle, haystack_len, needle_len, tmp1, tmp2, tmp3, tmp4, -1, result, ae); ++ ++ bind(DONE); ++ BLOCK_COMMENT("} string_indexof"); ++} ++ ++// string_indexof ++// result: x10 ++// src: x11 ++// src_count: x12 ++// pattern: x13 ++// pattern_count: x14 or 1/2/3/4 ++void MacroAssembler::string_indexof_linearscan(Register haystack, Register needle, ++ Register haystack_len, Register needle_len, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ int needle_con_cnt, Register result, int ae) ++{ ++ // Note: ++ // needle_con_cnt > 0 means needle_len register is invalid, needle length is constant ++ // for UU/LL: needle_con_cnt[1, 4], UL: needle_con_cnt = 1 ++ assert(needle_con_cnt <= 4, "Invalid needle constant count"); ++ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); ++ ++ Register ch1 = t0; ++ Register ch2 = t1; ++ Register hlen_neg = haystack_len, nlen_neg = needle_len; ++ Register nlen_tmp = tmp1, hlen_tmp = tmp2, result_tmp = tmp4; ++ ++ bool isLL = ae == StrIntrinsicNode::LL; ++ ++ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; ++ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; ++ int needle_chr_shift = needle_isL ? 0 : 1; ++ int haystack_chr_shift = haystack_isL ? 0 : 1; ++ int needle_chr_size = needle_isL ? 1 : 2; ++ int haystack_chr_size = haystack_isL ? 1 : 2; ++ ++ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : ++ (load_chr_insn)&MacroAssembler::lhu; ++ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : ++ (load_chr_insn)&MacroAssembler::lhu; ++ load_chr_insn load_2chr = isLL ? (load_chr_insn)&MacroAssembler::lhu : (load_chr_insn)&MacroAssembler::lwu; ++ load_chr_insn load_4chr = isLL ? (load_chr_insn)&MacroAssembler::lwu : (load_chr_insn)&MacroAssembler::ld; ++ ++ Label DO1, DO2, DO3, MATCH, NOMATCH, DONE; ++ ++ Register first = tmp3; ++ ++ if (needle_con_cnt == -1) { ++ Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT; ++ ++ sub(t0, needle_len, needle_isL == haystack_isL ? 4 : 2); ++ bltz(t0, DOSHORT); ++ ++ (this->*needle_load_1chr)(first, Address(needle), noreg); ++ slli(t0, needle_len, needle_chr_shift); ++ add(needle, needle, t0); ++ neg(nlen_neg, t0); ++ slli(t0, result_tmp, haystack_chr_shift); ++ add(haystack, haystack, t0); ++ neg(hlen_neg, t0); ++ ++ bind(FIRST_LOOP); ++ add(t0, haystack, hlen_neg); ++ (this->*haystack_load_1chr)(ch2, Address(t0), noreg); ++ beq(first, ch2, STR1_LOOP); ++ ++ bind(STR2_NEXT); ++ add(hlen_neg, hlen_neg, haystack_chr_size); ++ blez(hlen_neg, FIRST_LOOP); ++ j(NOMATCH); ++ ++ bind(STR1_LOOP); ++ add(nlen_tmp, nlen_neg, needle_chr_size); ++ add(hlen_tmp, hlen_neg, haystack_chr_size); ++ bgez(nlen_tmp, MATCH); ++ ++ bind(STR1_NEXT); ++ add(ch1, needle, nlen_tmp); ++ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); ++ add(ch2, haystack, hlen_tmp); ++ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); ++ bne(ch1, ch2, STR2_NEXT); ++ add(nlen_tmp, nlen_tmp, needle_chr_size); ++ add(hlen_tmp, hlen_tmp, haystack_chr_size); ++ bltz(nlen_tmp, STR1_NEXT); ++ j(MATCH); ++ ++ bind(DOSHORT); ++ if (needle_isL == haystack_isL) { ++ sub(t0, needle_len, 2); ++ bltz(t0, DO1); ++ bgtz(t0, DO3); ++ } ++ } ++ ++ if (needle_con_cnt == 4) { ++ Label CH1_LOOP; ++ (this->*load_4chr)(ch1, Address(needle), noreg); ++ sub(result_tmp, haystack_len, 4); ++ slli(tmp3, result_tmp, haystack_chr_shift); // result as tmp ++ add(haystack, haystack, tmp3); ++ neg(hlen_neg, tmp3); ++ ++ bind(CH1_LOOP); ++ add(ch2, haystack, hlen_neg); ++ (this->*load_4chr)(ch2, Address(ch2), noreg); ++ beq(ch1, ch2, MATCH); ++ add(hlen_neg, hlen_neg, haystack_chr_size); ++ blez(hlen_neg, CH1_LOOP); ++ j(NOMATCH); ++ } ++ ++ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 2) { ++ Label CH1_LOOP; ++ BLOCK_COMMENT("string_indexof DO2 {"); ++ bind(DO2); ++ (this->*load_2chr)(ch1, Address(needle), noreg); ++ if (needle_con_cnt == 2) { ++ sub(result_tmp, haystack_len, 2); ++ } ++ slli(tmp3, result_tmp, haystack_chr_shift); ++ add(haystack, haystack, tmp3); ++ neg(hlen_neg, tmp3); ++ ++ bind(CH1_LOOP); ++ add(tmp3, haystack, hlen_neg); ++ (this->*load_2chr)(ch2, Address(tmp3), noreg); ++ beq(ch1, ch2, MATCH); ++ add(hlen_neg, hlen_neg, haystack_chr_size); ++ blez(hlen_neg, CH1_LOOP); ++ j(NOMATCH); ++ BLOCK_COMMENT("} string_indexof DO2"); ++ } ++ ++ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 3) { ++ Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; ++ BLOCK_COMMENT("string_indexof DO3 {"); ++ ++ bind(DO3); ++ (this->*load_2chr)(first, Address(needle), noreg); ++ (this->*needle_load_1chr)(ch1, Address(needle, 2 * needle_chr_size), noreg); ++ if (needle_con_cnt == 3) { ++ sub(result_tmp, haystack_len, 3); ++ } ++ slli(hlen_tmp, result_tmp, haystack_chr_shift); ++ add(haystack, haystack, hlen_tmp); ++ neg(hlen_neg, hlen_tmp); ++ ++ bind(FIRST_LOOP); ++ add(ch2, haystack, hlen_neg); ++ (this->*load_2chr)(ch2, Address(ch2), noreg); ++ beq(first, ch2, STR1_LOOP); ++ ++ bind(STR2_NEXT); ++ add(hlen_neg, hlen_neg, haystack_chr_size); ++ blez(hlen_neg, FIRST_LOOP); ++ j(NOMATCH); ++ ++ bind(STR1_LOOP); ++ add(hlen_tmp, hlen_neg, 2 * haystack_chr_size); ++ add(ch2, haystack, hlen_tmp); ++ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); ++ bne(ch1, ch2, STR2_NEXT); ++ j(MATCH); ++ BLOCK_COMMENT("} string_indexof DO3"); ++ } ++ ++ if (needle_con_cnt == -1 || needle_con_cnt == 1) { ++ Label DO1_LOOP; ++ ++ BLOCK_COMMENT("string_indexof DO1 {"); ++ bind(DO1); ++ (this->*needle_load_1chr)(ch1, Address(needle), noreg); ++ sub(result_tmp, haystack_len, 1); ++ mv(tmp3, result_tmp); ++ if (haystack_chr_shift) { ++ slli(tmp3, result_tmp, haystack_chr_shift); ++ } ++ add(haystack, haystack, tmp3); ++ neg(hlen_neg, tmp3); ++ ++ bind(DO1_LOOP); ++ add(tmp3, haystack, hlen_neg); ++ (this->*haystack_load_1chr)(ch2, Address(tmp3), noreg); ++ beq(ch1, ch2, MATCH); ++ add(hlen_neg, hlen_neg, haystack_chr_size); ++ blez(hlen_neg, DO1_LOOP); ++ BLOCK_COMMENT("} string_indexof DO1"); ++ } ++ ++ bind(NOMATCH); ++ mv(result, -1); ++ j(DONE); ++ ++ bind(MATCH); ++ srai(t0, hlen_neg, haystack_chr_shift); ++ add(result, result_tmp, t0); ++ ++ bind(DONE); ++} ++ ++// Compare strings. ++void MacroAssembler::string_compare(Register str1, Register str2, ++ Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, ++ Register tmp3, int ae) ++{ ++ Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, ++ DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, ++ SHORT_LOOP_START, TAIL_CHECK, L; ++ ++ const int STUB_THRESHOLD = 64 + 8; ++ bool isLL = ae == StrIntrinsicNode::LL; ++ bool isLU = ae == StrIntrinsicNode::LU; ++ bool isUL = ae == StrIntrinsicNode::UL; ++ ++ bool str1_isL = isLL || isLU; ++ bool str2_isL = isLL || isUL; ++ ++ // for L strings, 1 byte for 1 character ++ // for U strings, 2 bytes for 1 character ++ int str1_chr_size = str1_isL ? 1 : 2; ++ int str2_chr_size = str2_isL ? 1 : 2; ++ int minCharsInWord = isLL ? wordSize : wordSize / 2; ++ ++ load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; ++ load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; ++ ++ BLOCK_COMMENT("string_compare {"); ++ ++ // Bizzarely, the counts are passed in bytes, regardless of whether they ++ // are L or U strings, however the result is always in characters. ++ if (!str1_isL) { ++ sraiw(cnt1, cnt1, 1); ++ } ++ if (!str2_isL) { ++ sraiw(cnt2, cnt2, 1); ++ } ++ ++ // Compute the minimum of the string lengths and save the difference in result. ++ sub(result, cnt1, cnt2); ++ bgt(cnt1, cnt2, L); ++ mv(cnt2, cnt1); ++ bind(L); ++ ++ // A very short string ++ mv(t0, minCharsInWord); ++ ble(cnt2, t0, SHORT_STRING); ++ ++ // Compare longwords ++ // load first parts of strings and finish initialization while loading ++ { ++ if (str1_isL == str2_isL) { // LL or UU ++ // load 8 bytes once to compare ++ ld(tmp1, Address(str1)); ++ beq(str1, str2, DONE); ++ ld(tmp2, Address(str2)); ++ mv(t0, STUB_THRESHOLD); ++ bge(cnt2, t0, STUB); ++ sub(cnt2, cnt2, minCharsInWord); ++ beqz(cnt2, TAIL_CHECK); ++ // convert cnt2 from characters to bytes ++ if (!str1_isL) { ++ slli(cnt2, cnt2, 1); ++ } ++ add(str2, str2, cnt2); ++ add(str1, str1, cnt2); ++ sub(cnt2, zr, cnt2); ++ } else if (isLU) { // LU case ++ lwu(tmp1, Address(str1)); ++ ld(tmp2, Address(str2)); ++ mv(t0, STUB_THRESHOLD); ++ bge(cnt2, t0, STUB); ++ addi(cnt2, cnt2, -4); ++ add(str1, str1, cnt2); ++ sub(cnt1, zr, cnt2); ++ slli(cnt2, cnt2, 1); ++ add(str2, str2, cnt2); ++ inflate_lo32(tmp3, tmp1); ++ mv(tmp1, tmp3); ++ sub(cnt2, zr, cnt2); ++ addi(cnt1, cnt1, 4); ++ } else { // UL case ++ ld(tmp1, Address(str1)); ++ lwu(tmp2, Address(str2)); ++ mv(t0, STUB_THRESHOLD); ++ bge(cnt2, t0, STUB); ++ addi(cnt2, cnt2, -4); ++ slli(t0, cnt2, 1); ++ sub(cnt1, zr, t0); ++ add(str1, str1, t0); ++ add(str2, str2, cnt2); ++ inflate_lo32(tmp3, tmp2); ++ mv(tmp2, tmp3); ++ sub(cnt2, zr, cnt2); ++ addi(cnt1, cnt1, 8); ++ } ++ addi(cnt2, cnt2, isUL ? 4 : 8); ++ bgez(cnt2, TAIL); ++ xorr(tmp3, tmp1, tmp2); ++ bnez(tmp3, DIFFERENCE); ++ ++ // main loop ++ bind(NEXT_WORD); ++ if (str1_isL == str2_isL) { // LL or UU ++ add(t0, str1, cnt2); ++ ld(tmp1, Address(t0)); ++ add(t0, str2, cnt2); ++ ld(tmp2, Address(t0)); ++ addi(cnt2, cnt2, 8); ++ } else if (isLU) { // LU case ++ add(t0, str1, cnt1); ++ lwu(tmp1, Address(t0)); ++ add(t0, str2, cnt2); ++ ld(tmp2, Address(t0)); ++ addi(cnt1, cnt1, 4); ++ inflate_lo32(tmp3, tmp1); ++ mv(tmp1, tmp3); ++ addi(cnt2, cnt2, 8); ++ } else { // UL case ++ add(t0, str2, cnt2); ++ lwu(tmp2, Address(t0)); ++ add(t0, str1, cnt1); ++ ld(tmp1, Address(t0)); ++ inflate_lo32(tmp3, tmp2); ++ mv(tmp2, tmp3); ++ addi(cnt1, cnt1, 8); ++ addi(cnt2, cnt2, 4); ++ } ++ bgez(cnt2, TAIL); ++ ++ xorr(tmp3, tmp1, tmp2); ++ beqz(tmp3, NEXT_WORD); ++ j(DIFFERENCE); ++ bind(TAIL); ++ xorr(tmp3, tmp1, tmp2); ++ bnez(tmp3, DIFFERENCE); ++ // Last longword. In the case where length == 4 we compare the ++ // same longword twice, but that's still faster than another ++ // conditional branch. ++ if (str1_isL == str2_isL) { // LL or UU ++ ld(tmp1, Address(str1)); ++ ld(tmp2, Address(str2)); ++ } else if (isLU) { // LU case ++ lwu(tmp1, Address(str1)); ++ ld(tmp2, Address(str2)); ++ inflate_lo32(tmp3, tmp1); ++ mv(tmp1, tmp3); ++ } else { // UL case ++ lwu(tmp2, Address(str2)); ++ ld(tmp1, Address(str1)); ++ inflate_lo32(tmp3, tmp2); ++ mv(tmp2, tmp3); ++ } ++ bind(TAIL_CHECK); ++ xorr(tmp3, tmp1, tmp2); ++ beqz(tmp3, DONE); ++ ++ // Find the first different characters in the longwords and ++ // compute their difference. ++ bind(DIFFERENCE); ++ ctzc_bit(result, tmp3, isLL); // count zero from lsb to msb ++ srl(tmp1, tmp1, result); ++ srl(tmp2, tmp2, result); ++ if (isLL) { ++ andi(tmp1, tmp1, 0xFF); ++ andi(tmp2, tmp2, 0xFF); ++ } else { ++ andi(tmp1, tmp1, 0xFFFF); ++ andi(tmp2, tmp2, 0xFFFF); ++ } ++ sub(result, tmp1, tmp2); ++ j(DONE); ++ } ++ ++ bind(STUB); ++ RuntimeAddress stub = NULL; ++ switch (ae) { ++ case StrIntrinsicNode::LL: ++ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LL()); ++ break; ++ case StrIntrinsicNode::UU: ++ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UU()); ++ break; ++ case StrIntrinsicNode::LU: ++ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LU()); ++ break; ++ case StrIntrinsicNode::UL: ++ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UL()); ++ break; ++ default: ++ ShouldNotReachHere(); ++ } ++ assert(stub.target() != NULL, "compare_long_string stub has not been generated"); ++ trampoline_call(stub); ++ j(DONE); ++ ++ bind(SHORT_STRING); ++ // Is the minimum length zero? ++ beqz(cnt2, DONE); ++ // arrange code to do most branches while loading and loading next characters ++ // while comparing previous ++ (this->*str1_load_chr)(tmp1, Address(str1), t0); ++ addi(str1, str1, str1_chr_size); ++ addi(cnt2, cnt2, -1); ++ beqz(cnt2, SHORT_LAST_INIT); ++ (this->*str2_load_chr)(cnt1, Address(str2), t0); ++ addi(str2, str2, str2_chr_size); ++ j(SHORT_LOOP_START); ++ bind(SHORT_LOOP); ++ addi(cnt2, cnt2, -1); ++ beqz(cnt2, SHORT_LAST); ++ bind(SHORT_LOOP_START); ++ (this->*str1_load_chr)(tmp2, Address(str1), t0); ++ addi(str1, str1, str1_chr_size); ++ (this->*str2_load_chr)(t0, Address(str2), t0); ++ addi(str2, str2, str2_chr_size); ++ bne(tmp1, cnt1, SHORT_LOOP_TAIL); ++ addi(cnt2, cnt2, -1); ++ beqz(cnt2, SHORT_LAST2); ++ (this->*str1_load_chr)(tmp1, Address(str1), t0); ++ addi(str1, str1, str1_chr_size); ++ (this->*str2_load_chr)(cnt1, Address(str2), t0); ++ addi(str2, str2, str2_chr_size); ++ beq(tmp2, t0, SHORT_LOOP); ++ sub(result, tmp2, t0); ++ j(DONE); ++ bind(SHORT_LOOP_TAIL); ++ sub(result, tmp1, cnt1); ++ j(DONE); ++ bind(SHORT_LAST2); ++ beq(tmp2, t0, DONE); ++ sub(result, tmp2, t0); ++ ++ j(DONE); ++ bind(SHORT_LAST_INIT); ++ (this->*str2_load_chr)(cnt1, Address(str2), t0); ++ addi(str2, str2, str2_chr_size); ++ bind(SHORT_LAST); ++ beq(tmp1, cnt1, DONE); ++ sub(result, tmp1, cnt1); ++ ++ bind(DONE); ++ ++ BLOCK_COMMENT("} string_compare"); ++} ++ ++void MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, ++ Register tmp4, Register tmp5, Register tmp6, Register result, ++ Register cnt1, int elem_size) { ++ Label DONE, SAME, NEXT_DWORD, SHORT, TAIL, TAIL2, IS_TMP5_ZR; ++ Register tmp1 = t0; ++ Register tmp2 = t1; ++ Register cnt2 = tmp2; // cnt2 only used in array length compare ++ Register elem_per_word = tmp6; ++ int log_elem_size = exact_log2(elem_size); ++ int length_offset = arrayOopDesc::length_offset_in_bytes(); ++ int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); ++ ++ assert(elem_size == 1 || elem_size == 2, "must be char or byte"); ++ assert_different_registers(a1, a2, result, cnt1, t0, t1, tmp3, tmp4, tmp5, tmp6); ++ mv(elem_per_word, wordSize / elem_size); ++ ++ BLOCK_COMMENT("arrays_equals {"); ++ ++ // if (a1 == a2), return true ++ beq(a1, a2, SAME); ++ ++ mv(result, false); ++ beqz(a1, DONE); ++ beqz(a2, DONE); ++ lwu(cnt1, Address(a1, length_offset)); ++ lwu(cnt2, Address(a2, length_offset)); ++ bne(cnt2, cnt1, DONE); ++ beqz(cnt1, SAME); ++ ++ slli(tmp5, cnt1, 3 + log_elem_size); ++ sub(tmp5, zr, tmp5); ++ add(a1, a1, base_offset); ++ add(a2, a2, base_offset); ++ ld(tmp3, Address(a1, 0)); ++ ld(tmp4, Address(a2, 0)); ++ ble(cnt1, elem_per_word, SHORT); // short or same ++ ++ // Main 16 byte comparison loop with 2 exits ++ bind(NEXT_DWORD); { ++ ld(tmp1, Address(a1, wordSize)); ++ ld(tmp2, Address(a2, wordSize)); ++ sub(cnt1, cnt1, 2 * wordSize / elem_size); ++ blez(cnt1, TAIL); ++ bne(tmp3, tmp4, DONE); ++ ld(tmp3, Address(a1, 2 * wordSize)); ++ ld(tmp4, Address(a2, 2 * wordSize)); ++ add(a1, a1, 2 * wordSize); ++ add(a2, a2, 2 * wordSize); ++ ble(cnt1, elem_per_word, TAIL2); ++ } beq(tmp1, tmp2, NEXT_DWORD); ++ j(DONE); ++ ++ bind(TAIL); ++ xorr(tmp4, tmp3, tmp4); ++ xorr(tmp2, tmp1, tmp2); ++ sll(tmp2, tmp2, tmp5); ++ orr(tmp5, tmp4, tmp2); ++ j(IS_TMP5_ZR); ++ ++ bind(TAIL2); ++ bne(tmp1, tmp2, DONE); ++ ++ bind(SHORT); ++ xorr(tmp4, tmp3, tmp4); ++ sll(tmp5, tmp4, tmp5); ++ ++ bind(IS_TMP5_ZR); ++ bnez(tmp5, DONE); ++ ++ bind(SAME); ++ mv(result, true); ++ // That's it. ++ bind(DONE); ++ ++ BLOCK_COMMENT("} array_equals"); ++} ++ ++// Compare Strings ++ ++// For Strings we're passed the address of the first characters in a1 ++// and a2 and the length in cnt1. ++// elem_size is the element size in bytes: either 1 or 2. ++// There are two implementations. For arrays >= 8 bytes, all ++// comparisons (including the final one, which may overlap) are ++// performed 8 bytes at a time. For strings < 8 bytes, we compare a ++// halfword, then a short, and then a byte. ++ ++void MacroAssembler::string_equals(Register a1, Register a2, ++ Register result, Register cnt1, int elem_size) ++{ ++ Label SAME, DONE, SHORT, NEXT_WORD; ++ Register tmp1 = t0; ++ Register tmp2 = t1; ++ ++ assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte"); ++ assert_different_registers(a1, a2, result, cnt1, t0, t1); ++ ++ BLOCK_COMMENT("string_equals {"); ++ ++ mv(result, false); ++ ++ // Check for short strings, i.e. smaller than wordSize. ++ sub(cnt1, cnt1, wordSize); ++ bltz(cnt1, SHORT); ++ ++ // Main 8 byte comparison loop. ++ bind(NEXT_WORD); { ++ ld(tmp1, Address(a1, 0)); ++ add(a1, a1, wordSize); ++ ld(tmp2, Address(a2, 0)); ++ add(a2, a2, wordSize); ++ sub(cnt1, cnt1, wordSize); ++ bne(tmp1, tmp2, DONE); ++ } bgtz(cnt1, NEXT_WORD); ++ ++ // Last longword. In the case where length == 4 we compare the ++ // same longword twice, but that's still faster than another ++ // conditional branch. ++ // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when ++ // length == 4. ++ add(tmp1, a1, cnt1); ++ ld(tmp1, Address(tmp1, 0)); ++ add(tmp2, a2, cnt1); ++ ld(tmp2, Address(tmp2, 0)); ++ bne(tmp1, tmp2, DONE); ++ j(SAME); ++ ++ bind(SHORT); ++ Label TAIL03, TAIL01; ++ ++ // 0-7 bytes left. ++ andi(t0, cnt1, 4); ++ beqz(t0, TAIL03); ++ { ++ lwu(tmp1, Address(a1, 0)); ++ add(a1, a1, 4); ++ lwu(tmp2, Address(a2, 0)); ++ add(a2, a2, 4); ++ bne(tmp1, tmp2, DONE); ++ } ++ ++ bind(TAIL03); ++ // 0-3 bytes left. ++ andi(t0, cnt1, 2); ++ beqz(t0, TAIL01); ++ { ++ lhu(tmp1, Address(a1, 0)); ++ add(a1, a1, 2); ++ lhu(tmp2, Address(a2, 0)); ++ add(a2, a2, 2); ++ bne(tmp1, tmp2, DONE); ++ } ++ ++ bind(TAIL01); ++ if (elem_size == 1) { // Only needed when comparing 1-byte elements ++ // 0-1 bytes left. ++ andi(t0, cnt1, 1); ++ beqz(t0, SAME); ++ { ++ lbu(tmp1, a1, 0); ++ lbu(tmp2, a2, 0); ++ bne(tmp1, tmp2, DONE); ++ } ++ } ++ ++ // Arrays are equal. ++ bind(SAME); ++ mv(result, true); ++ ++ // That's it. ++ bind(DONE); ++ BLOCK_COMMENT("} string_equals"); ++} ++ ++typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far); ++typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label, ++ bool is_far, bool is_unordered); ++ ++static conditional_branch_insn conditional_branches[] = ++{ ++ /* SHORT branches */ ++ (conditional_branch_insn)&Assembler::beq, ++ (conditional_branch_insn)&Assembler::bgt, ++ NULL, // BoolTest::overflow ++ (conditional_branch_insn)&Assembler::blt, ++ (conditional_branch_insn)&Assembler::bne, ++ (conditional_branch_insn)&Assembler::ble, ++ NULL, // BoolTest::no_overflow ++ (conditional_branch_insn)&Assembler::bge, ++ ++ /* UNSIGNED branches */ ++ (conditional_branch_insn)&Assembler::beq, ++ (conditional_branch_insn)&Assembler::bgtu, ++ NULL, ++ (conditional_branch_insn)&Assembler::bltu, ++ (conditional_branch_insn)&Assembler::bne, ++ (conditional_branch_insn)&Assembler::bleu, ++ NULL, ++ (conditional_branch_insn)&Assembler::bgeu ++}; ++ ++static float_conditional_branch_insn float_conditional_branches[] = ++{ ++ /* FLOAT SHORT branches */ ++ (float_conditional_branch_insn)&MacroAssembler::float_beq, ++ (float_conditional_branch_insn)&MacroAssembler::float_bgt, ++ NULL, // BoolTest::overflow ++ (float_conditional_branch_insn)&MacroAssembler::float_blt, ++ (float_conditional_branch_insn)&MacroAssembler::float_bne, ++ (float_conditional_branch_insn)&MacroAssembler::float_ble, ++ NULL, // BoolTest::no_overflow ++ (float_conditional_branch_insn)&MacroAssembler::float_bge, ++ ++ /* DOUBLE SHORT branches */ ++ (float_conditional_branch_insn)&MacroAssembler::double_beq, ++ (float_conditional_branch_insn)&MacroAssembler::double_bgt, ++ NULL, ++ (float_conditional_branch_insn)&MacroAssembler::double_blt, ++ (float_conditional_branch_insn)&MacroAssembler::double_bne, ++ (float_conditional_branch_insn)&MacroAssembler::double_ble, ++ NULL, ++ (float_conditional_branch_insn)&MacroAssembler::double_bge ++}; ++ ++void MacroAssembler::cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, bool is_far) { ++ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(conditional_branches) / sizeof(conditional_branches[0])), ++ "invalid conditional branch index"); ++ (this->*conditional_branches[cmpFlag])(op1, op2, label, is_far); ++} ++ ++// This is a function should only be used by C2. Flip the unordered when unordered-greater, C2 would use ++// unordered-lesser instead of unordered-greater. Finally, commute the result bits at function do_one_bytecode(). ++void MacroAssembler::float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, bool is_far) { ++ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(float_conditional_branches) / sizeof(float_conditional_branches[0])), ++ "invalid float conditional branch index"); ++ int booltest_flag = cmpFlag & ~(MacroAssembler::double_branch_mask); ++ (this->*float_conditional_branches[cmpFlag])(op1, op2, label, is_far, ++ (booltest_flag == (BoolTest::ge) || booltest_flag == (BoolTest::gt)) ? false : true); ++} ++ ++void MacroAssembler::enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { ++ switch (cmpFlag) { ++ case BoolTest::eq: ++ case BoolTest::le: ++ beqz(op1, L, is_far); ++ break; ++ case BoolTest::ne: ++ case BoolTest::gt: ++ bnez(op1, L, is_far); ++ break; ++ default: ++ ShouldNotReachHere(); + } +} -+#endif ++ ++void MacroAssembler::enc_cmpEqNe_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { ++ switch (cmpFlag) { ++ case BoolTest::eq: ++ beqz(op1, L, is_far); ++ break; ++ case BoolTest::ne: ++ bnez(op1, L, is_far); ++ break; ++ default: ++ ShouldNotReachHere(); ++ } ++} ++ ++void MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Register dst, Register src) { ++ Label L; ++ cmp_branch(cmpFlag ^ (1 << neg_cond_bits), op1, op2, L); ++ mv(dst, src); ++ bind(L); ++} ++ ++// Set dst to NaN if any NaN input. ++void MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRegister src2, ++ bool is_double, bool is_min) { ++ assert_different_registers(dst, src1, src2); ++ ++ Label Done; ++ fsflags(zr); ++ if (is_double) { ++ is_min ? fmin_d(dst, src1, src2) ++ : fmax_d(dst, src1, src2); ++ // Checking NaNs ++ flt_d(zr, src1, src2); ++ } else { ++ is_min ? fmin_s(dst, src1, src2) ++ : fmax_s(dst, src1, src2); ++ // Checking NaNs ++ flt_s(zr, src1, src2); ++ } ++ ++ frflags(t0); ++ beqz(t0, Done); ++ ++ // In case of NaNs ++ is_double ? fadd_d(dst, src1, src2) ++ : fadd_s(dst, src1, src2); ++ ++ bind(Done); ++} ++ ++#endif // COMPILER2 ++ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp new file mode 100644 -index 00000000000..23e09475be1 +index 0000000000..eca18b51f3 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -0,0 +1,858 @@ +@@ -0,0 +1,984 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -26576,8 +24402,7 @@ index 00000000000..23e09475be1 + +#include "asm/assembler.hpp" +#include "metaprogramming/enableIf.hpp" -+#include "oops/compressedOops.hpp" -+#include "utilities/powerOfTwo.hpp" ++#include "nativeInst_riscv.hpp" + +// MacroAssembler extends Assembler by frequently used macros. +// @@ -26591,13 +24416,40 @@ index 00000000000..23e09475be1 + } + virtual ~MacroAssembler() {} + -+ void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod); ++ void safepoint_poll(Label& slow_path); ++ void safepoint_poll_acquire(Label& slow_path); + -+ // Place a fence.i after code may have been modified due to a safepoint. -+ void safepoint_ifence(); ++ // Biased locking support ++ // lock_reg and obj_reg must be loaded up with the appropriate values. ++ // swap_reg is killed. ++ // tmp_reg must be supplied and must not be rscratch1 or rscratch2 ++ // Optional slow case is for implementations (interpreter and C1) which branch to ++ // slow case directly. Leaves condition codes set for C2's Fast_Lock node. ++ // Returns offset of first potentially-faulting instruction for null ++ // check info (currently consumed only by C1). If ++ // swap_reg_contains_mark is true then returns -1 as it is assumed ++ // the calling code has already passed any potential faults. ++ int biased_locking_enter(Register lock_reg, Register obj_reg, ++ Register swap_reg, Register tmp_reg, ++ bool swap_reg_contains_mark, ++ Label& done, Label* slow_case = NULL, ++ BiasedLockingCounters* counters = NULL, ++ Register flag = noreg); ++ void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done, Register flag = noreg); ++ ++ // Helper functions for statistics gathering. ++ // Unconditional atomic increment. ++ void atomic_incw(Register counter_addr, Register tmp); ++ void atomic_incw(Address counter_addr, Register tmp1, Register tmp2) { ++ la(tmp1, counter_addr); ++ atomic_incw(tmp1, tmp2); ++ } + + // Alignment + void align(int modulus, int extra_offset = 0); ++ static inline void assert_alignment(address pc, int alignment = NativeInstruction::instruction_size) { ++ assert(is_aligned(pc, alignment), "bad alignment"); ++ } + + // Stack frame creation/removal + // Note that SP must be updated to the right place before saving/restoring RA and FP @@ -26694,13 +24546,6 @@ index 00000000000..23e09475be1 + // thread in the default location (xthread) + void reset_last_Java_frame(bool clear_fp); + -+ void call_native(address entry_point, -+ Register arg_0); -+ void call_native_base( -+ address entry_point, // the entry point -+ Label* retaddr = NULL -+ ); -+ + virtual void call_VM_leaf_base( + address entry_point, // the entry point + int number_of_arguments, // the number of arguments to pop after the call @@ -26728,7 +24573,6 @@ index 00000000000..23e09475be1 + virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(Register java_thread); + -+ void resolve_weak_handle(Register result, Register tmp); + void resolve_oop_handle(Register result, Register tmp = x15); + void resolve_jobject(Register value, Register thread, Register tmp); + @@ -26771,6 +24615,8 @@ index 00000000000..23e09475be1 + // stored using routines that take a jobject. + void store_heap_oop_null(Address dst); + ++ void load_prototype_header(Register dst, Register src); ++ + // This dummy is to prevent a call to store_heap_oop from + // converting a zero (linke NULL) into a Register by giving + // the compiler two choices it can't resolve @@ -27025,18 +24871,17 @@ index 00000000000..23e09475be1 + void double_blt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + void double_bgt(FloatRegister Rs1, FloatRegister Rs2, Label &l, bool is_far = false, bool is_unordered = false); + -+ void push_reg(RegSet regs, Register stack) { if (regs.bits()) { push_reg(regs.bits(), stack); } } -+ void pop_reg(RegSet regs, Register stack) { if (regs.bits()) { pop_reg(regs.bits(), stack); } } ++private: ++ int push_reg(unsigned int bitset, Register stack); ++ int pop_reg(unsigned int bitset, Register stack); ++ int push_fp(unsigned int bitset, Register stack); ++ int pop_fp(unsigned int bitset, Register stack); ++ ++public: + void push_reg(Register Rs); + void pop_reg(Register Rd); -+ int push_reg(unsigned int bitset, Register stack); -+ int pop_reg(unsigned int bitset, Register stack); -+ void push_fp(FloatRegSet regs, Register stack) { if (regs.bits()) push_fp(regs.bits(), stack); } -+ void pop_fp(FloatRegSet regs, Register stack) { if (regs.bits()) pop_fp(regs.bits(), stack); } -+#ifdef COMPILER2 -+ void push_vp(VectorRegSet regs, Register stack) { if (regs.bits()) push_vp(regs.bits(), stack); } -+ void pop_vp(VectorRegSet regs, Register stack) { if (regs.bits()) pop_vp(regs.bits(), stack); } -+#endif // COMPILER2 ++ void push_reg(RegSet regs, Register stack) { if (regs.bits()) push_reg(regs.bits(), stack); } ++ void pop_reg(RegSet regs, Register stack) { if (regs.bits()) pop_reg(regs.bits(), stack); } + + // Push and pop everything that might be clobbered by a native + // runtime call except t0 and t1. (They are always @@ -27054,8 +24899,8 @@ index 00000000000..23e09475be1 + + void pusha(); + void popa(); -+ void push_CPU_state(bool save_vectors = false, int vector_size_in_bytes = 0); -+ void pop_CPU_state(bool restore_vectors = false, int vector_size_in_bytes = 0); ++ void push_CPU_state(); ++ void pop_CPU_state(); + + // if heap base register is used - reinit it with the correct value + void reinit_heapbase(); @@ -27067,15 +24912,18 @@ index 00000000000..23e09475be1 + } + + // mv -+ template::value)> -+ inline void mv(Register Rd, T o) { -+ li(Rd, (int64_t)o); -+ } ++ void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); } ++ ++ inline void mv(Register Rd, int imm64) { li(Rd, (int64_t)imm64); } ++ inline void mv(Register Rd, long imm64) { li(Rd, (int64_t)imm64); } ++ inline void mv(Register Rd, long long imm64) { li(Rd, (int64_t)imm64); } ++ inline void mv(Register Rd, unsigned int imm64) { li(Rd, (int64_t)imm64); } ++ inline void mv(Register Rd, unsigned long imm64) { li(Rd, (int64_t)imm64); } ++ inline void mv(Register Rd, unsigned long long imm64) { li(Rd, (int64_t)imm64); } + + inline void mvw(Register Rd, int32_t imm32) { mv(Rd, imm32); } + + void mv(Register Rd, Address dest); -+ void mv(Register Rd, address addr); + void mv(Register Rd, RegisterOrConstant src); + + // logic @@ -27178,21 +25026,33 @@ index 00000000000..23e09475be1 + + void reserved_stack_check(); + -+ void get_polling_page(Register dest, relocInfo::relocType rtype); -+ address read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); ++ virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, ++ Register tmp, ++ int offset); ++ ++ void get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype); ++ void read_polling_page(Register r, address page, relocInfo::relocType rtype); ++ void read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); + + address trampoline_call(Address entry, CodeBuffer* cbuf = NULL); + address ic_call(address entry, jint method_index = 0); + -+ void add_memory_int64(const Address dst, int64_t imm); -+ void add_memory_int32(const Address dst, int32_t imm); ++ // Support for memory inc/dec ++ // n.b. increment/decrement calls with an Address destination will ++ // need to use a scratch register to load the value to be ++ // incremented. increment/decrement calls which add or subtract a ++ // constant value other than sign-extended 12-bit immediate will need ++ // to use a 2nd scratch register to hold the constant. so, an address ++ // increment/decrement may trash both t0 and t1. ++ ++ void increment(const Address dst, int64_t value = 1); ++ void incrementw(const Address dst, int32_t value = 1); ++ ++ void decrement(const Address dst, int64_t value = 1); ++ void decrementw(const Address dst, int32_t value = 1); + + void cmpptr(Register src1, Address src2, Label& equal); + -+ void clinit_barrier(Register klass, Register tmp, Label* L_fast_path = NULL, Label* L_slow_path = NULL); -+ void load_method_holder_cld(Register result, Register method); -+ void load_method_holder(Register holder, Register method); -+ + void compute_index(Register str1, Register trailing_zeros, Register match_mask, + Register result, Register char_tmp, Register tmp, + bool haystack_isL); @@ -27327,12 +25187,6 @@ index 00000000000..23e09475be1 + // if [src1 < src2], dst = -1; + void cmp_l2i(Register dst, Register src1, Register src2, Register tmp = t0); + -+ int push_fp(unsigned int bitset, Register stack); -+ int pop_fp(unsigned int bitset, Register stack); -+ -+ int push_vp(unsigned int bitset, Register stack); -+ int pop_vp(unsigned int bitset, Register stack); -+ + // vext + void vmnot_m(VectorRegister vd, VectorRegister vs); + void vncvt_x_x_w(VectorRegister vd, VectorRegister vs, VectorMask vm = unmasked); @@ -27341,23 +25195,20 @@ index 00000000000..23e09475be1 +private: + +#ifdef ASSERT -+ // Template short-hand support to clean-up after a failed call to trampoline ++ // Macro short-hand support to clean-up after a failed call to trampoline + // call generation (see trampoline_call() below), when a set of Labels must + // be reset (before returning). -+ template -+ void reset_labels(Label& lbl, More&... more) { -+ lbl.reset(); reset_labels(more...); -+ } -+ template -+ void reset_labels(Label& lbl) { -+ lbl.reset(); -+ } ++#define reset_labels1(L1) L1.reset() ++#define reset_labels2(L1, L2) L1.reset(); L2.reset() ++#define reset_labels3(L1, L2, L3) L1.reset(); reset_labels2(L2, L3) ++#define reset_labels5(L1, L2, L3, L4, L5) reset_labels2(L1, L2); reset_labels3(L3, L4, L5) +#endif + void repne_scan(Register addr, Register value, Register count, Register tmp); + + // Return true if an address is within the 48-bit RISCV64 address space. + bool is_valid_riscv64_address(address addr) { -+ return ((uintptr_t)addr >> 48) == 0; ++ // sv48: must have bits 63–48 all equal to bit 47 ++ return ((uintptr_t)addr >> 47) == 0; + } + + void ld_constant(Register dest, const Address &const_addr) { @@ -27376,8 +25227,109 @@ index 00000000000..23e09475be1 + void load_reserved(Register addr, enum operand_size size, Assembler::Aqrl acquire); + void store_conditional(Register addr, Register new_val, enum operand_size size, Assembler::Aqrl release); + -+ // Check the current thread doesn't need a cross modify fence. -+ void verify_cross_modify_fence_not_required() PRODUCT_RETURN; ++public: ++ void string_compare(Register str1, Register str2, ++ Register cnt1, Register cnt2, Register result, ++ Register tmp1, Register tmp2, Register tmp3, ++ int ae); ++ ++ void string_indexof_char_short(Register str1, Register cnt1, ++ Register ch, Register result, ++ bool isL); ++ ++ void string_indexof_char(Register str1, Register cnt1, ++ Register ch, Register result, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ bool isL); ++ ++ void string_indexof(Register str1, Register str2, ++ Register cnt1, Register cnt2, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ Register tmp5, Register tmp6, ++ Register result, int ae); ++ ++ void string_indexof_linearscan(Register haystack, Register needle, ++ Register haystack_len, Register needle_len, ++ Register tmp1, Register tmp2, ++ Register tmp3, Register tmp4, ++ int needle_con_cnt, Register result, int ae); ++ ++ void arrays_equals(Register r1, Register r2, ++ Register tmp3, Register tmp4, ++ Register tmp5, Register tmp6, ++ Register result, Register cnt1, ++ int elem_size); ++ ++ void string_equals(Register r1, Register r2, ++ Register result, Register cnt1, ++ int elem_size); ++ ++ // refer to conditional_branches and float_conditional_branches ++ static const int bool_test_bits = 3; ++ static const int neg_cond_bits = 2; ++ static const int unsigned_branch_mask = 1 << bool_test_bits; ++ static const int double_branch_mask = 1 << bool_test_bits; ++ ++ // cmp ++ void cmp_branch(int cmpFlag, ++ Register op1, Register op2, ++ Label& label, bool is_far = false); ++ ++ void float_cmp_branch(int cmpFlag, ++ FloatRegister op1, FloatRegister op2, ++ Label& label, bool is_far = false); ++ ++ void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, ++ Label& L, bool is_far = false); ++ ++ void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, ++ Label& L, bool is_far = false); ++ ++ void enc_cmove(int cmpFlag, ++ Register op1, Register op2, ++ Register dst, Register src); ++ ++ void spill(Register r, bool is64, int offset) { ++ is64 ? sd(r, Address(sp, offset)) ++ : sw(r, Address(sp, offset)); ++ } ++ ++ void spill(FloatRegister f, bool is64, int offset) { ++ is64 ? fsd(f, Address(sp, offset)) ++ : fsw(f, Address(sp, offset)); ++ } ++ ++ void spill(VectorRegister v, int offset) { ++ add(t0, sp, offset); ++ vs1r_v(v, t0); ++ } ++ ++ void unspill(Register r, bool is64, int offset) { ++ is64 ? ld(r, Address(sp, offset)) ++ : lw(r, Address(sp, offset)); ++ } ++ ++ void unspillu(Register r, bool is64, int offset) { ++ is64 ? ld(r, Address(sp, offset)) ++ : lwu(r, Address(sp, offset)); ++ } ++ ++ void unspill(FloatRegister f, bool is64, int offset) { ++ is64 ? fld(f, Address(sp, offset)) ++ : flw(f, Address(sp, offset)); ++ } ++ ++ void unspill(VectorRegister v, int offset) { ++ add(t0, sp, offset); ++ vl1r_v(v, t0); ++ } ++ ++ void minmax_FD(FloatRegister dst, ++ FloatRegister src1, FloatRegister src2, ++ bool is_double, bool is_min); ++ +}; + +#ifdef ASSERT @@ -27405,7 +25357,7 @@ index 00000000000..23e09475be1 +#endif // CPU_RISCV_MACROASSEMBLER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp new file mode 100644 -index 00000000000..ef968ccd96d +index 0000000000..ef968ccd96 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.inline.hpp @@ -0,0 +1,31 @@ @@ -27440,187 +25392,12 @@ index 00000000000..ef968ccd96d +// Still empty. + +#endif // CPU_RISCV_MACROASSEMBLER_RISCV_INLINE_HPP -diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp -new file mode 100644 -index 00000000000..23a75d20502 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp -@@ -0,0 +1,169 @@ -+/* -+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_MATCHER_RISCV_HPP -+#define CPU_RISCV_MATCHER_RISCV_HPP -+ -+ // Defined within class Matcher -+ -+ // false => size gets scaled to BytesPerLong, ok. -+ static const bool init_array_count_is_in_bytes = false; -+ -+ // Whether this platform implements the scalable vector feature -+ static const bool implements_scalable_vector = true; -+ -+ static const bool supports_scalable_vector() { -+ return UseRVV; -+ } -+ -+ // riscv supports misaligned vectors store/load. -+ static constexpr bool misaligned_vectors_ok() { -+ return true; -+ } -+ -+ // Whether code generation need accurate ConvI2L types. -+ static const bool convi2l_type_required = false; -+ -+ // Does the CPU require late expand (see block.cpp for description of late expand)? -+ static const bool require_postalloc_expand = false; -+ -+ // Do we need to mask the count passed to shift instructions or does -+ // the cpu only look at the lower 5/6 bits anyway? -+ static const bool need_masked_shift_count = false; -+ -+ // No support for generic vector operands. -+ static const bool supports_generic_vector_operands = false; -+ -+ static constexpr bool isSimpleConstant64(jlong value) { -+ // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. -+ // Probably always true, even if a temp register is required. -+ return true; -+ } -+ -+ // Use conditional move (CMOVL) -+ static constexpr int long_cmove_cost() { -+ // long cmoves are no more expensive than int cmoves -+ return 0; -+ } -+ -+ static constexpr int float_cmove_cost() { -+ // float cmoves are no more expensive than int cmoves -+ return 0; -+ } -+ -+ // This affects two different things: -+ // - how Decode nodes are matched -+ // - how ImplicitNullCheck opportunities are recognized -+ // If true, the matcher will try to remove all Decodes and match them -+ // (as operands) into nodes. NullChecks are not prepared to deal with -+ // Decodes by final_graph_reshaping(). -+ // If false, final_graph_reshaping() forces the decode behind the Cmp -+ // for a NullCheck. The matcher matches the Decode node into a register. -+ // Implicit_null_check optimization moves the Decode along with the -+ // memory operation back up before the NullCheck. -+ static bool narrow_oop_use_complex_address() { -+ return CompressedOops::shift() == 0; -+ } -+ -+ static bool narrow_klass_use_complex_address() { -+ return false; -+ } -+ -+ static bool const_oop_prefer_decode() { -+ // Prefer ConN+DecodeN over ConP in simple compressed oops mode. -+ return CompressedOops::base() == NULL; -+ } -+ -+ static bool const_klass_prefer_decode() { -+ // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. -+ return CompressedKlassPointers::base() == NULL; -+ } -+ -+ // Is it better to copy float constants, or load them directly from -+ // memory? Intel can load a float constant from a direct address, -+ // requiring no extra registers. Most RISCs will have to materialize -+ // an address into a register first, so they would do better to copy -+ // the constant from stack. -+ static const bool rematerialize_float_constants = false; -+ -+ // If CPU can load and store mis-aligned doubles directly then no -+ // fixup is needed. Else we split the double into 2 integer pieces -+ // and move it piece-by-piece. Only happens when passing doubles into -+ // C code as the Java calling convention forces doubles to be aligned. -+ static const bool misaligned_doubles_ok = true; -+ -+ // Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. -+ static const bool strict_fp_requires_explicit_rounding = false; -+ -+ // Are floats converted to double when stored to stack during -+ // deoptimization? -+ static constexpr bool float_in_double() { return false; } -+ -+ // Do ints take an entire long register or just half? -+ // The relevant question is how the int is callee-saved: -+ // the whole long is written but de-opt'ing will have to extract -+ // the relevant 32 bits. -+ static const bool int_in_long = true; -+ -+ // Does the CPU supports vector variable shift instructions? -+ static constexpr bool supports_vector_variable_shifts(void) { -+ return false; -+ } -+ -+ // Does the CPU supports vector variable rotate instructions? -+ static constexpr bool supports_vector_variable_rotates(void) { -+ return false; -+ } -+ -+ // Does the CPU supports vector constant rotate instructions? -+ static constexpr bool supports_vector_constant_rotates(int shift) { -+ return false; -+ } -+ -+ // Does the CPU supports vector unsigned comparison instructions? -+ static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { -+ return false; -+ } -+ -+ // Some microarchitectures have mask registers used on vectors -+ static const bool has_predicated_vectors(void) { -+ return false; -+ } -+ -+ // true means we have fast l2f convers -+ // false means that conversion is done by runtime call -+ static constexpr bool convL2FSupported(void) { -+ return true; -+ } -+ -+ // Implements a variant of EncodeISOArrayNode that encode ASCII only -+ static const bool supports_encode_ascii_array = false; -+ -+ // Returns pre-selection estimated size of a vector operation. -+ static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { -+ return 0; -+ } -+ -+#endif // CPU_RISCV_MATCHER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp new file mode 100644 -index 00000000000..1f7c0c87c21 +index 0000000000..3c4e8847ce --- /dev/null +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -0,0 +1,461 @@ +@@ -0,0 +1,444 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -27650,7 +25427,6 @@ index 00000000000..1f7c0c87c21 +#include "precompiled.hpp" +#include "asm/macroAssembler.hpp" +#include "classfile/javaClasses.inline.hpp" -+#include "classfile/vmClasses.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" +#include "memory/allocation.inline.hpp" @@ -27671,12 +25447,11 @@ index 00000000000..1f7c0c87c21 +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) { -+ assert_cond(_masm != NULL); + if (VerifyMethodHandles) { -+ verify_klass(_masm, klass_reg, VM_CLASS_ID(java_lang_Class), ++ verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class), + "MH argument is a Class"); + } -+ __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset())); ++ __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset_in_bytes())); +} + +#ifdef ASSERT @@ -27691,11 +25466,10 @@ index 00000000000..1f7c0c87c21 + +#ifdef ASSERT +void MethodHandles::verify_klass(MacroAssembler* _masm, -+ Register obj, vmClassID klass_id, ++ Register obj, SystemDictionary::WKID klass_id, + const char* error_message) { -+ assert_cond(_masm != NULL); -+ InstanceKlass** klass_addr = vmClasses::klass_addr_at(klass_id); -+ Klass* klass = vmClasses::klass_at(klass_id); ++ InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); ++ Klass* klass = SystemDictionary::well_known_klass(klass_id); + Register temp = t1; + Register temp2 = t0; // used by MacroAssembler::cmpptr + Label L_ok, L_bad; @@ -27722,7 +25496,6 @@ index 00000000000..1f7c0c87c21 + +void MethodHandles::jump_from_method_handle(MacroAssembler* _masm, Register method, Register temp, + bool for_compiler_entry) { -+ assert_cond(_masm != NULL); + assert(method == xmethod, "interpreter calling convention"); + Label L_no_such_method; + __ beqz(xmethod, L_no_such_method); @@ -27753,7 +25526,6 @@ index 00000000000..1f7c0c87c21 + Register recv, Register method_temp, + Register temp2, + bool for_compiler_entry) { -+ assert_cond(_masm != NULL); + BLOCK_COMMENT("jump_to_lambda_form {"); + // This is the initial entry point of a lazy method handle. + // After type checking, it picks up the invoker from the LambdaForm. @@ -27763,13 +25535,13 @@ index 00000000000..1f7c0c87c21 + + // Load the invoker, as MH -> MH.form -> LF.vmentry + __ verify_oop(recv); -+ __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset())), temp2); ++ __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), temp2); + __ verify_oop(method_temp); -+ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset())), temp2); ++ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), temp2); + __ verify_oop(method_temp); -+ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset())), temp2); ++ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), temp2); + __ verify_oop(method_temp); -+ __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())), noreg, noreg); ++ __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())), noreg, noreg); + + if (VerifyMethodHandles && !for_compiler_entry) { + // make sure recv is already on stack @@ -27792,7 +25564,6 @@ index 00000000000..1f7c0c87c21 +// Code generation +address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* _masm, + vmIntrinsics::ID iid) { -+ assert_cond(_masm != NULL); + const bool not_for_compiler_entry = false; // this is the interpreter entry + assert(is_signature_polymorphic(iid), "expected invoke iid"); + if (iid == vmIntrinsics::_invokeGeneric || @@ -27804,13 +25575,6 @@ index 00000000000..1f7c0c87c21 + return NULL; + } + -+ // No need in interpreter entry for linkToNative for now. -+ // Interpreter calls compiled entry through i2c. -+ if (iid == vmIntrinsics::_linkToNative) { -+ __ ebreak(); -+ return NULL; -+ } -+ + // x30: sender SP (must preserve; see prepare_to_jump_from_interpreted) + // xmethod: Method* + // x13: argument locator (parameter slot count, added to sp) @@ -27887,7 +25651,6 @@ index 00000000000..1f7c0c87c21 + Register receiver_reg, + Register member_reg, + bool for_compiler_entry) { -+ assert_cond(_masm != NULL); + assert(is_signature_polymorphic(iid), "expected invoke iid"); + // temps used in this code are not used in *either* compiled or interpreted calling sequences + Register temp1 = x7; @@ -27903,24 +25666,21 @@ index 00000000000..1f7c0c87c21 + assert_different_registers(temp1, temp2, temp3, receiver_reg); + assert_different_registers(temp1, temp2, temp3, member_reg); + -+ if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { -+ if (iid == vmIntrinsics::_linkToNative) { -+ assert(for_compiler_entry, "only compiler entry is supported"); -+ } ++ if (iid == vmIntrinsics::_invokeBasic) { + // indirect through MH.form.vmentry.vmtarget + jump_to_lambda_form(_masm, receiver_reg, xmethod, temp1, for_compiler_entry); + } else { + // The method is a member invoker used by direct method handles. + if (VerifyMethodHandles) { + // make sure the trailing argument really is a MemberName (caller responsibility) -+ verify_klass(_masm, member_reg, VM_CLASS_ID(java_lang_invoke_MemberName), ++ verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_invoke_MemberName), + "MemberName required for invokeVirtual etc."); + } + -+ Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset())); -+ Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset())); -+ Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset())); -+ Address vmtarget_method( xmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())); ++ Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); ++ Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); ++ Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); ++ Address vmtarget_method( xmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); + + Register temp1_recv_klass = temp1; + if (iid != vmIntrinsics::_linkToStatic) { @@ -28044,7 +25804,7 @@ index 00000000000..1f7c0c87c21 + } + + default: -+ fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid)); ++ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); + break; + } + @@ -28084,7 +25844,7 @@ index 00000000000..1f7c0c87c21 +#endif //PRODUCT diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp new file mode 100644 -index 00000000000..f73aba29d67 +index 0000000000..65493eba76 --- /dev/null +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp @@ -0,0 +1,57 @@ @@ -28126,11 +25886,11 @@ index 00000000000..f73aba29d67 + static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg); + + static void verify_klass(MacroAssembler* _masm, -+ Register obj, vmClassID klass_id, ++ Register obj, SystemDictionary::WKID klass_id, + const char* error_message = "wrong klass") NOT_DEBUG_RETURN; + + static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { -+ verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle), ++ verify_klass(_masm, mh_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_invoke_MethodHandle), + "reference is a MH"); + } + @@ -28147,10 +25907,10 @@ index 00000000000..f73aba29d67 + bool for_compiler_entry); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp new file mode 100644 -index 00000000000..0a05c577860 +index 0000000000..ecce8eb021 --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -@@ -0,0 +1,429 @@ +@@ -0,0 +1,414 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -28242,7 +26002,7 @@ index 00000000000..0a05c577860 + is_addi_at(instr + instruction_size) && // Addi + is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 + is_addi_at(instr + instruction_size * 3) && // Addi -+ is_slli_shift_at(instr + instruction_size * 4, 5) && // Slli Rd, Rs, 5 ++ is_slli_shift_at(instr + instruction_size * 4, 6) && // Slli Rd, Rs, 6 + (is_addi_at(instr + instruction_size * 5) || + is_jalr_at(instr + instruction_size * 5) || + is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load @@ -28255,18 +26015,6 @@ index 00000000000..0a05c577860 + check_li32_data_dependency(instr); +} + -+bool NativeInstruction::is_li64_at(address instr) { -+ return is_lui_at(instr) && // lui -+ is_addi_at(instr + instruction_size) && // addi -+ is_slli_shift_at(instr + instruction_size * 2, 12) && // Slli Rd, Rs, 12 -+ is_addi_at(instr + instruction_size * 3) && // addi -+ is_slli_shift_at(instr + instruction_size * 4, 12) && // Slli Rd, Rs, 12 -+ is_addi_at(instr + instruction_size * 5) && // addi -+ is_slli_shift_at(instr + instruction_size * 6, 8) && // Slli Rd, Rs, 8 -+ is_addi_at(instr + instruction_size * 7) && // addi -+ check_li64_data_dependency(instr); -+} -+ +void NativeCall::verify() { + assert(NativeCall::is_call_at((address)this), "unexpected code at call site"); +} @@ -28299,8 +26047,7 @@ index 00000000000..0a05c577860 +// during code generation, where no patching lock is needed. +void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { + assert(!assert_lock || -+ (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || -+ CompiledICLocker::is_safe(addr_at(0)), ++ (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()), + "concurrent code patching"); + + ResourceMark rm; @@ -28418,6 +26165,13 @@ index 00000000000..0a05c577860 + + +void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) { ++ // Patching to not_entrant can happen while activations of the method are ++ // in use. The patching in that instance must happen only when certain ++ // alignment restrictions are true. These guarantees check those ++ // conditions. ++ ++ // Must be 4 bytes aligned ++ MacroAssembler::assert_alignment(verified_entry); +} + + @@ -28426,15 +26180,9 @@ index 00000000000..0a05c577860 + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about -+ // As a special case we also use sequence movptr_with_offset(r,0), jalr(r,0) -+ // i.e. jump to 0 when we need leave space for a wide immediate -+ // load -+ -+ // return -1 if jump to self or to 0 -+ if ((dest == (address) this) || dest == 0) { -+ dest = (address) -1; -+ } + ++ // return -1 if jump to self ++ dest = (dest == (address) this) ? (address) -1 : dest; + return dest; +}; + @@ -28456,14 +26204,9 @@ index 00000000000..0a05c577860 + + // We use jump to self as the unresolved address which the inline + // cache code (and relocs) know about -+ // As a special case we also use jump to 0 when first generating -+ // a general jump -+ -+ // return -1 if jump to self or to 0 -+ if ((dest == (address) this) || dest == 0) { -+ dest = (address) -1; -+ } + ++ // return -1 if jump to self ++ dest = (dest == (address) this) ? (address) -1 : dest; + return dest; +} + @@ -28508,6 +26251,8 @@ index 00000000000..0a05c577860 + nativeInstruction_at(verified_entry)->is_sigill_zombie_not_entrant(), + "riscv cannot replace non-jump with jump"); + ++ check_verified_entry_alignment(entry, verified_entry); ++ + // Patch this nmethod atomically. + if (Assembler::reachable_from_branch_at(verified_entry, dest)) { + ptrdiff_t offset = dest - verified_entry; @@ -28582,10 +26327,10 @@ index 00000000000..0a05c577860 +} diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp new file mode 100644 -index 00000000000..718b2e3de6c +index 0000000000..183ab85fc9 --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp -@@ -0,0 +1,572 @@ +@@ -0,0 +1,520 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved. @@ -28629,7 +26374,6 @@ index 00000000000..718b2e3de6c +// - - NativeIllegalInstruction +// - - NativeCallTrampolineStub +// - - NativeMembar -+// - - NativeFenceI + +// The base class for different kinds of native instruction abstractions. +// Provides the primitive operations to manipulate code relative to this. @@ -28703,40 +26447,6 @@ index 00000000000..718b2e3de6c + extract_rs1(last_instr) == extract_rd(slli2); + } + -+ // the instruction sequence of li64 is as below: -+ // lui -+ // addi -+ // slli -+ // addi -+ // slli -+ // addi -+ // slli -+ // addi -+ static bool check_li64_data_dependency(address instr) { -+ address lui = instr; -+ address addi1 = lui + instruction_size; -+ address slli1 = addi1 + instruction_size; -+ address addi2 = slli1 + instruction_size; -+ address slli2 = addi2 + instruction_size; -+ address addi3 = slli2 + instruction_size; -+ address slli3 = addi3 + instruction_size; -+ address addi4 = slli3 + instruction_size; -+ return extract_rs1(addi1) == extract_rd(lui) && -+ extract_rs1(addi1) == extract_rd(addi1) && -+ extract_rs1(slli1) == extract_rd(addi1) && -+ extract_rs1(slli1) == extract_rd(slli1) && -+ extract_rs1(addi2) == extract_rd(slli1) && -+ extract_rs1(addi2) == extract_rd(addi2) && -+ extract_rs1(slli2) == extract_rd(addi2) && -+ extract_rs1(slli2) == extract_rd(slli2) && -+ extract_rs1(addi3) == extract_rd(slli2) && -+ extract_rs1(addi3) == extract_rd(addi3) && -+ extract_rs1(slli3) == extract_rd(addi3) && -+ extract_rs1(slli3) == extract_rd(slli3) && -+ extract_rs1(addi4) == extract_rd(slli3) && -+ extract_rs1(addi4) == extract_rd(addi4); -+ } -+ + // the instruction sequence of li32 is as below: + // lui + // addiw @@ -28771,7 +26481,6 @@ index 00000000000..718b2e3de6c + + static bool is_movptr_at(address instr); + static bool is_li32_at(address instr); -+ static bool is_li64_at(address instr); + static bool is_pc_relative_at(address branch); + static bool is_load_pc_relative_at(address branch); + @@ -28899,18 +26608,14 @@ index 00000000000..718b2e3de6c +inline NativeCall* nativeCall_at(address addr) { + assert_cond(addr != NULL); + NativeCall* call = (NativeCall*)(addr - NativeCall::instruction_offset); -+#ifdef ASSERT -+ call->verify(); -+#endif ++ DEBUG_ONLY(call->verify()); + return call; +} + +inline NativeCall* nativeCall_before(address return_address) { + assert_cond(return_address != NULL); + NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset); -+#ifdef ASSERT -+ call->verify(); -+#endif ++ DEBUG_ONLY(call->verify()); + return call; +} + @@ -28950,7 +26655,7 @@ index 00000000000..718b2e3de6c + } + + intptr_t data() const; -+ void set_data(intptr_t x); ++ void set_data(intptr_t x); + + void flush() { + if (!maybe_cpool_ref(instruction_address())) { @@ -28958,8 +26663,8 @@ index 00000000000..718b2e3de6c + } + } + -+ void verify(); -+ void print(); ++ void verify(); ++ void print(); + + // Creation + inline friend NativeMovConstReg* nativeMovConstReg_at(address addr); @@ -28969,55 +26674,53 @@ index 00000000000..718b2e3de6c +inline NativeMovConstReg* nativeMovConstReg_at(address addr) { + assert_cond(addr != NULL); + NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_offset); -+#ifdef ASSERT -+ test->verify(); -+#endif ++ DEBUG_ONLY(test->verify()); + return test; +} + +inline NativeMovConstReg* nativeMovConstReg_before(address addr) { + assert_cond(addr != NULL); + NativeMovConstReg* test = (NativeMovConstReg*)(addr - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset); -+#ifdef ASSERT -+ test->verify(); -+#endif ++ DEBUG_ONLY(test->verify()); + return test; +} + -+// RISCV should not use C1 runtime patching, so just leave NativeMovRegMem Unimplemented. ++// RISCV should not use C1 runtime patching, but still implement ++// NativeMovRegMem to keep some compilers happy. +class NativeMovRegMem: public NativeInstruction { + public: -+ int instruction_start() const { -+ Unimplemented(); -+ return 0; -+ } ++ enum RISCV_specific_constants { ++ instruction_size = NativeInstruction::instruction_size, ++ instruction_offset = 0, ++ data_offset = 0, ++ next_instruction_offset = NativeInstruction::instruction_size ++ }; + -+ address instruction_address() const { -+ Unimplemented(); -+ return NULL; -+ } ++ int instruction_start() const { return instruction_offset; } + -+ int num_bytes_to_end_of_patch() const { -+ Unimplemented(); -+ return 0; -+ } ++ address instruction_address() const { return addr_at(instruction_offset); } ++ ++ int num_bytes_to_end_of_patch() const { return instruction_offset + instruction_size; } + + int offset() const; + + void set_offset(int x); + -+ void add_offset_in_bytes(int add_offset) { Unimplemented(); } ++ void add_offset_in_bytes(int add_offset) { ++ set_offset(offset() + add_offset); ++ } + + void verify(); + void print(); + + private: -+ inline friend NativeMovRegMem* nativeMovRegMem_at (address addr); ++ inline friend NativeMovRegMem* nativeMovRegMem_at(address addr); +}; + -+inline NativeMovRegMem* nativeMovRegMem_at (address addr) { -+ Unimplemented(); -+ return NULL; ++inline NativeMovRegMem* nativeMovRegMem_at(address addr) { ++ NativeMovRegMem* test = (NativeMovRegMem*)(addr - NativeMovRegMem::instruction_offset); ++ DEBUG_ONLY(test->verify()); ++ return test; +} + +class NativeJump: public NativeInstruction { @@ -29048,9 +26751,7 @@ index 00000000000..718b2e3de6c + +inline NativeJump* nativeJump_at(address addr) { + NativeJump* jump = (NativeJump*)(addr - NativeJump::instruction_offset); -+#ifdef ASSERT -+ jump->verify(); -+#endif ++ DEBUG_ONLY(jump->verify()); + return jump; +} + @@ -29149,72 +26850,13 @@ index 00000000000..718b2e3de6c + return (NativeMembar*)addr; +} + -+class NativeFenceI : public NativeInstruction { -+public: -+ static inline int instruction_size() { -+ // 2 for fence.i + fence -+ return (UseConservativeFence ? 2 : 1) * NativeInstruction::instruction_size; -+ } -+}; -+ +#endif // CPU_RISCV_NATIVEINST_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.cpp b/src/hotspot/cpu/riscv/registerMap_riscv.cpp -new file mode 100644 -index 00000000000..26c1edc36ff ---- /dev/null -+++ b/src/hotspot/cpu/riscv/registerMap_riscv.cpp -@@ -0,0 +1,45 @@ -+/* -+ * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2021, Huawei Technologies Co., Ltd. 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 "runtime/registerMap.hpp" -+#include "vmreg_riscv.inline.hpp" -+ -+address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { -+ if (base_reg->is_VectorRegister()) { -+ assert(base_reg->is_concrete(), "must pass base reg"); -+ int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_fpr) / -+ VectorRegisterImpl::max_slots_per_register; -+ intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; -+ address base_location = location(base_reg); -+ if (base_location != NULL) { -+ return base_location + offset_in_bytes; -+ } else { -+ return NULL; -+ } -+ } else { -+ return location(base_reg->next(slot_idx)); -+ } -+} diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.hpp b/src/hotspot/cpu/riscv/registerMap_riscv.hpp new file mode 100644 -index 00000000000..f34349811a9 +index 0000000000..fef8ca9b64 --- /dev/null +++ b/src/hotspot/cpu/riscv/registerMap_riscv.hpp -@@ -0,0 +1,43 @@ +@@ -0,0 +1,42 @@ +/* + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -29250,7 +26892,6 @@ index 00000000000..f34349811a9 + // This is the hook for finding a register in an "well-known" location, + // such as a register block of a predetermined format. + address pd_location(VMReg reg) const { return NULL; } -+ address pd_location(VMReg base_reg, int slot_idx) const; + + // no PD state to clear or copy: + void pd_clear() {} @@ -29258,12 +26899,210 @@ index 00000000000..f34349811a9 + void pd_initialize_from(const RegisterMap* map) {} + +#endif // CPU_RISCV_REGISTERMAP_RISCV_HPP +diff --git a/src/hotspot/cpu/riscv/register_definitions_riscv.cpp b/src/hotspot/cpu/riscv/register_definitions_riscv.cpp +new file mode 100644 +index 0000000000..583f67573c +--- /dev/null ++++ b/src/hotspot/cpu/riscv/register_definitions_riscv.cpp +@@ -0,0 +1,192 @@ ++/* ++ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2014, Red Hat Inc. All rights reserved. ++ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ * ++ */ ++ ++#include "precompiled.hpp" ++#include "asm/assembler.hpp" ++#include "asm/register.hpp" ++#include "interp_masm_riscv.hpp" ++#include "register_riscv.hpp" ++ ++REGISTER_DEFINITION(Register, noreg); ++ ++REGISTER_DEFINITION(Register, x0); ++REGISTER_DEFINITION(Register, x1); ++REGISTER_DEFINITION(Register, x2); ++REGISTER_DEFINITION(Register, x3); ++REGISTER_DEFINITION(Register, x4); ++REGISTER_DEFINITION(Register, x5); ++REGISTER_DEFINITION(Register, x6); ++REGISTER_DEFINITION(Register, x7); ++REGISTER_DEFINITION(Register, x8); ++REGISTER_DEFINITION(Register, x9); ++REGISTER_DEFINITION(Register, x10); ++REGISTER_DEFINITION(Register, x11); ++REGISTER_DEFINITION(Register, x12); ++REGISTER_DEFINITION(Register, x13); ++REGISTER_DEFINITION(Register, x14); ++REGISTER_DEFINITION(Register, x15); ++REGISTER_DEFINITION(Register, x16); ++REGISTER_DEFINITION(Register, x17); ++REGISTER_DEFINITION(Register, x18); ++REGISTER_DEFINITION(Register, x19); ++REGISTER_DEFINITION(Register, x20); ++REGISTER_DEFINITION(Register, x21); ++REGISTER_DEFINITION(Register, x22); ++REGISTER_DEFINITION(Register, x23); ++REGISTER_DEFINITION(Register, x24); ++REGISTER_DEFINITION(Register, x25); ++REGISTER_DEFINITION(Register, x26); ++REGISTER_DEFINITION(Register, x27); ++REGISTER_DEFINITION(Register, x28); ++REGISTER_DEFINITION(Register, x29); ++REGISTER_DEFINITION(Register, x30); ++REGISTER_DEFINITION(Register, x31); ++ ++REGISTER_DEFINITION(FloatRegister, fnoreg); ++ ++REGISTER_DEFINITION(FloatRegister, f0); ++REGISTER_DEFINITION(FloatRegister, f1); ++REGISTER_DEFINITION(FloatRegister, f2); ++REGISTER_DEFINITION(FloatRegister, f3); ++REGISTER_DEFINITION(FloatRegister, f4); ++REGISTER_DEFINITION(FloatRegister, f5); ++REGISTER_DEFINITION(FloatRegister, f6); ++REGISTER_DEFINITION(FloatRegister, f7); ++REGISTER_DEFINITION(FloatRegister, f8); ++REGISTER_DEFINITION(FloatRegister, f9); ++REGISTER_DEFINITION(FloatRegister, f10); ++REGISTER_DEFINITION(FloatRegister, f11); ++REGISTER_DEFINITION(FloatRegister, f12); ++REGISTER_DEFINITION(FloatRegister, f13); ++REGISTER_DEFINITION(FloatRegister, f14); ++REGISTER_DEFINITION(FloatRegister, f15); ++REGISTER_DEFINITION(FloatRegister, f16); ++REGISTER_DEFINITION(FloatRegister, f17); ++REGISTER_DEFINITION(FloatRegister, f18); ++REGISTER_DEFINITION(FloatRegister, f19); ++REGISTER_DEFINITION(FloatRegister, f20); ++REGISTER_DEFINITION(FloatRegister, f21); ++REGISTER_DEFINITION(FloatRegister, f22); ++REGISTER_DEFINITION(FloatRegister, f23); ++REGISTER_DEFINITION(FloatRegister, f24); ++REGISTER_DEFINITION(FloatRegister, f25); ++REGISTER_DEFINITION(FloatRegister, f26); ++REGISTER_DEFINITION(FloatRegister, f27); ++REGISTER_DEFINITION(FloatRegister, f28); ++REGISTER_DEFINITION(FloatRegister, f29); ++REGISTER_DEFINITION(FloatRegister, f30); ++REGISTER_DEFINITION(FloatRegister, f31); ++ ++REGISTER_DEFINITION(VectorRegister, vnoreg); ++ ++REGISTER_DEFINITION(VectorRegister, v0); ++REGISTER_DEFINITION(VectorRegister, v1); ++REGISTER_DEFINITION(VectorRegister, v2); ++REGISTER_DEFINITION(VectorRegister, v3); ++REGISTER_DEFINITION(VectorRegister, v4); ++REGISTER_DEFINITION(VectorRegister, v5); ++REGISTER_DEFINITION(VectorRegister, v6); ++REGISTER_DEFINITION(VectorRegister, v7); ++REGISTER_DEFINITION(VectorRegister, v8); ++REGISTER_DEFINITION(VectorRegister, v9); ++REGISTER_DEFINITION(VectorRegister, v10); ++REGISTER_DEFINITION(VectorRegister, v11); ++REGISTER_DEFINITION(VectorRegister, v12); ++REGISTER_DEFINITION(VectorRegister, v13); ++REGISTER_DEFINITION(VectorRegister, v14); ++REGISTER_DEFINITION(VectorRegister, v15); ++REGISTER_DEFINITION(VectorRegister, v16); ++REGISTER_DEFINITION(VectorRegister, v17); ++REGISTER_DEFINITION(VectorRegister, v18); ++REGISTER_DEFINITION(VectorRegister, v19); ++REGISTER_DEFINITION(VectorRegister, v20); ++REGISTER_DEFINITION(VectorRegister, v21); ++REGISTER_DEFINITION(VectorRegister, v22); ++REGISTER_DEFINITION(VectorRegister, v23); ++REGISTER_DEFINITION(VectorRegister, v24); ++REGISTER_DEFINITION(VectorRegister, v25); ++REGISTER_DEFINITION(VectorRegister, v26); ++REGISTER_DEFINITION(VectorRegister, v27); ++REGISTER_DEFINITION(VectorRegister, v28); ++REGISTER_DEFINITION(VectorRegister, v29); ++REGISTER_DEFINITION(VectorRegister, v30); ++REGISTER_DEFINITION(VectorRegister, v31); ++ ++REGISTER_DEFINITION(Register, c_rarg0); ++REGISTER_DEFINITION(Register, c_rarg1); ++REGISTER_DEFINITION(Register, c_rarg2); ++REGISTER_DEFINITION(Register, c_rarg3); ++REGISTER_DEFINITION(Register, c_rarg4); ++REGISTER_DEFINITION(Register, c_rarg5); ++REGISTER_DEFINITION(Register, c_rarg6); ++REGISTER_DEFINITION(Register, c_rarg7); ++ ++REGISTER_DEFINITION(FloatRegister, c_farg0); ++REGISTER_DEFINITION(FloatRegister, c_farg1); ++REGISTER_DEFINITION(FloatRegister, c_farg2); ++REGISTER_DEFINITION(FloatRegister, c_farg3); ++REGISTER_DEFINITION(FloatRegister, c_farg4); ++REGISTER_DEFINITION(FloatRegister, c_farg5); ++REGISTER_DEFINITION(FloatRegister, c_farg6); ++REGISTER_DEFINITION(FloatRegister, c_farg7); ++ ++REGISTER_DEFINITION(Register, j_rarg0); ++REGISTER_DEFINITION(Register, j_rarg1); ++REGISTER_DEFINITION(Register, j_rarg2); ++REGISTER_DEFINITION(Register, j_rarg3); ++REGISTER_DEFINITION(Register, j_rarg4); ++REGISTER_DEFINITION(Register, j_rarg5); ++REGISTER_DEFINITION(Register, j_rarg6); ++REGISTER_DEFINITION(Register, j_rarg7); ++ ++REGISTER_DEFINITION(FloatRegister, j_farg0); ++REGISTER_DEFINITION(FloatRegister, j_farg1); ++REGISTER_DEFINITION(FloatRegister, j_farg2); ++REGISTER_DEFINITION(FloatRegister, j_farg3); ++REGISTER_DEFINITION(FloatRegister, j_farg4); ++REGISTER_DEFINITION(FloatRegister, j_farg5); ++REGISTER_DEFINITION(FloatRegister, j_farg6); ++REGISTER_DEFINITION(FloatRegister, j_farg7); ++ ++REGISTER_DEFINITION(Register, zr); ++REGISTER_DEFINITION(Register, gp); ++REGISTER_DEFINITION(Register, tp); ++REGISTER_DEFINITION(Register, xmethod); ++REGISTER_DEFINITION(Register, ra); ++REGISTER_DEFINITION(Register, sp); ++REGISTER_DEFINITION(Register, fp); ++REGISTER_DEFINITION(Register, xheapbase); ++REGISTER_DEFINITION(Register, xcpool); ++REGISTER_DEFINITION(Register, xmonitors); ++REGISTER_DEFINITION(Register, xlocals); ++REGISTER_DEFINITION(Register, xthread); ++REGISTER_DEFINITION(Register, xbcp); ++REGISTER_DEFINITION(Register, xdispatch); ++REGISTER_DEFINITION(Register, esp); ++ ++REGISTER_DEFINITION(Register, t0); ++REGISTER_DEFINITION(Register, t1); ++REGISTER_DEFINITION(Register, t2); diff --git a/src/hotspot/cpu/riscv/register_riscv.cpp b/src/hotspot/cpu/riscv/register_riscv.cpp new file mode 100644 -index 00000000000..f8116e9df8c +index 0000000000..ef60cb3bb0 --- /dev/null +++ b/src/hotspot/cpu/riscv/register_riscv.cpp -@@ -0,0 +1,73 @@ +@@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -29292,10 +27131,6 @@ index 00000000000..f8116e9df8c +#include "precompiled.hpp" +#include "register_riscv.hpp" + -+REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_registers); -+REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); -+REGISTER_IMPL_DEFINITION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); -+ +const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * + RegisterImpl::max_slots_per_register; + @@ -29303,11 +27138,6 @@ index 00000000000..f8116e9df8c + ConcreteRegisterImpl::max_gpr + + FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register; + -+const int ConcreteRegisterImpl::max_vpr = -+ ConcreteRegisterImpl::max_fpr + -+ VectorRegisterImpl::number_of_registers * VectorRegisterImpl::max_slots_per_register; -+ -+ +const char* RegisterImpl::name() const { + static const char *const names[number_of_registers] = { + "zr", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "x9", @@ -29339,10 +27169,10 @@ index 00000000000..f8116e9df8c +} diff --git a/src/hotspot/cpu/riscv/register_riscv.hpp b/src/hotspot/cpu/riscv/register_riscv.hpp new file mode 100644 -index 00000000000..a9200cac647 +index 0000000000..f64a06eb89 --- /dev/null +++ b/src/hotspot/cpu/riscv/register_riscv.hpp -@@ -0,0 +1,324 @@ +@@ -0,0 +1,381 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -29392,13 +27222,13 @@ index 00000000000..a9200cac647 + +// Use Register as shortcut +class RegisterImpl; -+typedef const RegisterImpl* Register; ++typedef RegisterImpl* Register; + -+inline constexpr Register as_Register(int encoding); ++inline Register as_Register(int encoding) { ++ return (Register)(intptr_t) encoding; ++} + +class RegisterImpl: public AbstractRegisterImpl { -+ static constexpr Register first(); -+ + public: + enum { + number_of_registers = 32, @@ -29411,16 +27241,16 @@ index 00000000000..a9200cac647 + }; + + // derived registers, offsets, and addresses -+ const Register successor() const { return this + 1; } ++ const Register successor() const { return as_Register(encoding() + 1); } + + // construction -+ inline friend constexpr Register as_Register(int encoding); ++ inline friend Register as_Register(int encoding); + + VMReg as_VMReg() const; + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -+ int encoding_nocheck() const { return this - first(); } ++ int encoding_nocheck() const { return (intptr_t)this; } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + @@ -29438,9 +27268,11 @@ index 00000000000..a9200cac647 + return encoding_nocheck() >= compressed_register_base && + encoding_nocheck() <= compressed_register_top; + } -+}; + -+REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_registers); ++ // Return the bit which represents this register. This is intended ++ // to be ORed into a bitmask: for usage see class RegSet below. ++ uint64_t bit(bool should_set = true) const { return should_set ? 1 << encoding() : 0; } ++}; + +// The integer registers of the RISCV architecture + @@ -29481,14 +27313,14 @@ index 00000000000..a9200cac647 + +// Use FloatRegister as shortcut +class FloatRegisterImpl; -+typedef const FloatRegisterImpl* FloatRegister; ++typedef FloatRegisterImpl* FloatRegister; + -+inline constexpr FloatRegister as_FloatRegister(int encoding); ++inline FloatRegister as_FloatRegister(int encoding) { ++ return (FloatRegister)(intptr_t) encoding; ++} + +// The implementation of floating point registers for the architecture +class FloatRegisterImpl: public AbstractRegisterImpl { -+ static constexpr FloatRegister first(); -+ + public: + enum { + number_of_registers = 32, @@ -29500,18 +27332,16 @@ index 00000000000..a9200cac647 + }; + + // construction -+ inline friend constexpr FloatRegister as_FloatRegister(int encoding); ++ inline friend FloatRegister as_FloatRegister(int encoding); + + VMReg as_VMReg() const; + + // derived registers, offsets, and addresses -+ FloatRegister successor() const { -+ return as_FloatRegister((encoding() + 1) % (unsigned)number_of_registers); -+ } ++ FloatRegister successor() const { return as_FloatRegister(encoding() + 1); } + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -+ int encoding_nocheck() const { return this - first(); } ++ int encoding_nocheck() const { return (intptr_t)this; } + int is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + @@ -29531,8 +27361,6 @@ index 00000000000..a9200cac647 + } +}; + -+REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); -+ +// The float registers of the RISCV architecture + +CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1)); @@ -29572,14 +27400,14 @@ index 00000000000..a9200cac647 + +// Use VectorRegister as shortcut +class VectorRegisterImpl; -+typedef const VectorRegisterImpl* VectorRegister; ++typedef VectorRegisterImpl* VectorRegister; + -+inline constexpr VectorRegister as_VectorRegister(int encoding); ++inline VectorRegister as_VectorRegister(int encoding) { ++ return (VectorRegister)(intptr_t) encoding; ++} + +// The implementation of vector registers for RVV +class VectorRegisterImpl: public AbstractRegisterImpl { -+ static constexpr VectorRegister first(); -+ + public: + enum { + number_of_registers = 32, @@ -29587,23 +27415,21 @@ index 00000000000..a9200cac647 + }; + + // construction -+ inline friend constexpr VectorRegister as_VectorRegister(int encoding); ++ inline friend VectorRegister as_VectorRegister(int encoding); + + VMReg as_VMReg() const; + + // derived registers, offsets, and addresses -+ VectorRegister successor() const { return this + 1; } ++ VectorRegister successor() const { return as_VectorRegister(encoding() + 1); } + + // accessors + int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -+ int encoding_nocheck() const { return this - first(); } ++ int encoding_nocheck() const { return (intptr_t)this; } + bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } + const char* name() const; + +}; + -+REGISTER_IMPL_DECLARATION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); -+ +// The vector registers of RVV +CONSTANT_REGISTER_DECLARATION(VectorRegister, vnoreg , (-1)); + @@ -29652,27 +27478,88 @@ index 00000000000..a9200cac647 + // it's optoregs. + + number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers + -+ FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + -+ VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers) ++ FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers) + }; + + // added to make it compile + static const int max_gpr; + static const int max_fpr; -+ static const int max_vpr; +}; + -+typedef AbstractRegSet RegSet; -+typedef AbstractRegSet FloatRegSet; -+typedef AbstractRegSet VectorRegSet; ++// A set of registers ++class RegSet { ++ uint32_t _bitset; ++ ++ RegSet(uint32_t bitset) : _bitset(bitset) { } ++ ++public: ++ ++ RegSet() : _bitset(0) { } ++ ++ RegSet(Register r1) : _bitset(r1->bit()) { } ++ ++ RegSet operator+(const RegSet aSet) const { ++ RegSet result(_bitset | aSet._bitset); ++ return result; ++ } ++ ++ RegSet operator-(const RegSet aSet) const { ++ RegSet result(_bitset & ~aSet._bitset); ++ return result; ++ } ++ ++ RegSet &operator+=(const RegSet aSet) { ++ *this = *this + aSet; ++ return *this; ++ } ++ ++ RegSet &operator-=(const RegSet aSet) { ++ *this = *this - aSet; ++ return *this; ++ } ++ ++ static RegSet of(Register r1) { ++ return RegSet(r1); ++ } ++ ++ static RegSet of(Register r1, Register r2) { ++ return of(r1) + r2; ++ } ++ ++ static RegSet of(Register r1, Register r2, Register r3) { ++ return of(r1, r2) + r3; ++ } ++ ++ static RegSet of(Register r1, Register r2, Register r3, Register r4) { ++ return of(r1, r2, r3) + r4; ++ } ++ ++ static RegSet range(Register start, Register end) { ++ uint32_t bits = ~0; ++ bits <<= start->encoding(); ++ bits <<= 31 - end->encoding(); ++ bits >>= 31 - end->encoding(); ++ ++ return RegSet(bits); ++ } ++ ++ uint32_t bits() const { return _bitset; } ++ ++private: ++ ++ Register first() { ++ uint32_t first = _bitset & -_bitset; ++ return first ? as_Register(exact_log2(first)) : noreg; ++ } ++}; + +#endif // CPU_RISCV_REGISTER_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp new file mode 100644 -index 00000000000..228a64eae2c +index 0000000000..047ea2276c --- /dev/null +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp -@@ -0,0 +1,113 @@ +@@ -0,0 +1,112 @@ +/* + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -29716,7 +27603,6 @@ index 00000000000..228a64eae2c + switch (type()) { + case relocInfo::oop_type: { + oop_Relocation *reloc = (oop_Relocation *)this; -+ // in movoop when BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate + if (NativeInstruction::is_load_pc_relative_at(addr())) { + address constptr = (address)code()->oop_addr_at(reloc->oop_index()); + bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); @@ -29788,7 +27674,7 @@ index 00000000000..228a64eae2c +} diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.hpp b/src/hotspot/cpu/riscv/relocInfo_riscv.hpp new file mode 100644 -index 00000000000..840ed935d88 +index 0000000000..840ed935d8 --- /dev/null +++ b/src/hotspot/cpu/riscv/relocInfo_riscv.hpp @@ -0,0 +1,44 @@ @@ -29838,10 +27724,10 @@ index 00000000000..840ed935d88 +#endif // CPU_RISCV_RELOCINFO_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad new file mode 100644 -index 00000000000..588887e1d96 +index 0000000000..d54ae97200 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -0,0 +1,10611 @@ +@@ -0,0 +1,10273 @@ +// +// Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -29928,8 +27814,8 @@ index 00000000000..588887e1d96 +reg_def R0_H ( NS, NS, Op_RegI, 0, x0->as_VMReg()->next() ); +reg_def R1 ( NS, SOC, Op_RegI, 1, x1->as_VMReg() ); // ra +reg_def R1_H ( NS, SOC, Op_RegI, 1, x1->as_VMReg()->next() ); -+reg_def R2 ( NS, SOE, Op_RegI, 2, x2->as_VMReg() ); // sp -+reg_def R2_H ( NS, SOE, Op_RegI, 2, x2->as_VMReg()->next() ); ++reg_def R2 ( NS, NS, Op_RegI, 2, x2->as_VMReg() ); // sp ++reg_def R2_H ( NS, NS, Op_RegI, 2, x2->as_VMReg()->next() ); +reg_def R3 ( NS, NS, Op_RegI, 3, x3->as_VMReg() ); // gp +reg_def R3_H ( NS, NS, Op_RegI, 3, x3->as_VMReg()->next() ); +reg_def R4 ( NS, NS, Op_RegI, 4, x4->as_VMReg() ); // tp @@ -30071,177 +27957,6 @@ index 00000000000..588887e1d96 +reg_def F31_H ( SOC, SOC, Op_RegF, 31, f31->as_VMReg()->next() ); + +// ---------------------------- -+// Vector Registers -+// ---------------------------- -+ -+// For RVV vector registers, we simply extend vector register size to 4 -+// 'logical' slots. This is nominally 128 bits but it actually covers -+// all possible 'physical' RVV vector register lengths from 128 ~ 1024 -+// bits. The 'physical' RVV vector register length is detected during -+// startup, so the register allocator is able to identify the correct -+// number of bytes needed for an RVV spill/unspill. -+ -+reg_def V0 ( SOC, SOC, Op_VecA, 0, v0->as_VMReg() ); -+reg_def V0_H ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next() ); -+reg_def V0_J ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(2) ); -+reg_def V0_K ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(3) ); -+ -+reg_def V1 ( SOC, SOC, Op_VecA, 1, v1->as_VMReg() ); -+reg_def V1_H ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next() ); -+reg_def V1_J ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(2) ); -+reg_def V1_K ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(3) ); -+ -+reg_def V2 ( SOC, SOC, Op_VecA, 2, v2->as_VMReg() ); -+reg_def V2_H ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next() ); -+reg_def V2_J ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(2) ); -+reg_def V2_K ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(3) ); -+ -+reg_def V3 ( SOC, SOC, Op_VecA, 3, v3->as_VMReg() ); -+reg_def V3_H ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next() ); -+reg_def V3_J ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(2) ); -+reg_def V3_K ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(3) ); -+ -+reg_def V4 ( SOC, SOC, Op_VecA, 4, v4->as_VMReg() ); -+reg_def V4_H ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next() ); -+reg_def V4_J ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(2) ); -+reg_def V4_K ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(3) ); -+ -+reg_def V5 ( SOC, SOC, Op_VecA, 5, v5->as_VMReg() ); -+reg_def V5_H ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next() ); -+reg_def V5_J ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(2) ); -+reg_def V5_K ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(3) ); -+ -+reg_def V6 ( SOC, SOC, Op_VecA, 6, v6->as_VMReg() ); -+reg_def V6_H ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next() ); -+reg_def V6_J ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(2) ); -+reg_def V6_K ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(3) ); -+ -+reg_def V7 ( SOC, SOC, Op_VecA, 7, v7->as_VMReg() ); -+reg_def V7_H ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next() ); -+reg_def V7_J ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(2) ); -+reg_def V7_K ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(3) ); -+ -+reg_def V8 ( SOC, SOC, Op_VecA, 8, v8->as_VMReg() ); -+reg_def V8_H ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next() ); -+reg_def V8_J ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(2) ); -+reg_def V8_K ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(3) ); -+ -+reg_def V9 ( SOC, SOC, Op_VecA, 9, v9->as_VMReg() ); -+reg_def V9_H ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next() ); -+reg_def V9_J ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(2) ); -+reg_def V9_K ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(3) ); -+ -+reg_def V10 ( SOC, SOC, Op_VecA, 10, v10->as_VMReg() ); -+reg_def V10_H ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next() ); -+reg_def V10_J ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(2) ); -+reg_def V10_K ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(3) ); -+ -+reg_def V11 ( SOC, SOC, Op_VecA, 11, v11->as_VMReg() ); -+reg_def V11_H ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next() ); -+reg_def V11_J ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(2) ); -+reg_def V11_K ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(3) ); -+ -+reg_def V12 ( SOC, SOC, Op_VecA, 12, v12->as_VMReg() ); -+reg_def V12_H ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next() ); -+reg_def V12_J ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(2) ); -+reg_def V12_K ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(3) ); -+ -+reg_def V13 ( SOC, SOC, Op_VecA, 13, v13->as_VMReg() ); -+reg_def V13_H ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next() ); -+reg_def V13_J ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(2) ); -+reg_def V13_K ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(3) ); -+ -+reg_def V14 ( SOC, SOC, Op_VecA, 14, v14->as_VMReg() ); -+reg_def V14_H ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next() ); -+reg_def V14_J ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(2) ); -+reg_def V14_K ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(3) ); -+ -+reg_def V15 ( SOC, SOC, Op_VecA, 15, v15->as_VMReg() ); -+reg_def V15_H ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next() ); -+reg_def V15_J ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(2) ); -+reg_def V15_K ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(3) ); -+ -+reg_def V16 ( SOC, SOC, Op_VecA, 16, v16->as_VMReg() ); -+reg_def V16_H ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next() ); -+reg_def V16_J ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(2) ); -+reg_def V16_K ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(3) ); -+ -+reg_def V17 ( SOC, SOC, Op_VecA, 17, v17->as_VMReg() ); -+reg_def V17_H ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next() ); -+reg_def V17_J ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(2) ); -+reg_def V17_K ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(3) ); -+ -+reg_def V18 ( SOC, SOC, Op_VecA, 18, v18->as_VMReg() ); -+reg_def V18_H ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next() ); -+reg_def V18_J ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(2) ); -+reg_def V18_K ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(3) ); -+ -+reg_def V19 ( SOC, SOC, Op_VecA, 19, v19->as_VMReg() ); -+reg_def V19_H ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next() ); -+reg_def V19_J ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(2) ); -+reg_def V19_K ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(3) ); -+ -+reg_def V20 ( SOC, SOC, Op_VecA, 20, v20->as_VMReg() ); -+reg_def V20_H ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next() ); -+reg_def V20_J ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(2) ); -+reg_def V20_K ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(3) ); -+ -+reg_def V21 ( SOC, SOC, Op_VecA, 21, v21->as_VMReg() ); -+reg_def V21_H ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next() ); -+reg_def V21_J ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(2) ); -+reg_def V21_K ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(3) ); -+ -+reg_def V22 ( SOC, SOC, Op_VecA, 22, v22->as_VMReg() ); -+reg_def V22_H ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next() ); -+reg_def V22_J ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(2) ); -+reg_def V22_K ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(3) ); -+ -+reg_def V23 ( SOC, SOC, Op_VecA, 23, v23->as_VMReg() ); -+reg_def V23_H ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next() ); -+reg_def V23_J ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(2) ); -+reg_def V23_K ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(3) ); -+ -+reg_def V24 ( SOC, SOC, Op_VecA, 24, v24->as_VMReg() ); -+reg_def V24_H ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next() ); -+reg_def V24_J ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(2) ); -+reg_def V24_K ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(3) ); -+ -+reg_def V25 ( SOC, SOC, Op_VecA, 25, v25->as_VMReg() ); -+reg_def V25_H ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next() ); -+reg_def V25_J ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(2) ); -+reg_def V25_K ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(3) ); -+ -+reg_def V26 ( SOC, SOC, Op_VecA, 26, v26->as_VMReg() ); -+reg_def V26_H ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next() ); -+reg_def V26_J ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(2) ); -+reg_def V26_K ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(3) ); -+ -+reg_def V27 ( SOC, SOC, Op_VecA, 27, v27->as_VMReg() ); -+reg_def V27_H ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next() ); -+reg_def V27_J ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(2) ); -+reg_def V27_K ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(3) ); -+ -+reg_def V28 ( SOC, SOC, Op_VecA, 28, v28->as_VMReg() ); -+reg_def V28_H ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next() ); -+reg_def V28_J ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(2) ); -+reg_def V28_K ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(3) ); -+ -+reg_def V29 ( SOC, SOC, Op_VecA, 29, v29->as_VMReg() ); -+reg_def V29_H ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next() ); -+reg_def V29_J ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(2) ); -+reg_def V29_K ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(3) ); -+ -+reg_def V30 ( SOC, SOC, Op_VecA, 30, v30->as_VMReg() ); -+reg_def V30_H ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next() ); -+reg_def V30_J ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(2) ); -+reg_def V30_K ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(3) ); -+ -+reg_def V31 ( SOC, SOC, Op_VecA, 31, v31->as_VMReg() ); -+reg_def V31_H ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next() ); -+reg_def V31_J ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(2) ); -+reg_def V31_K ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(3) ); -+ -+// ---------------------------- +// Special Registers +// ---------------------------- + @@ -30339,48 +28054,15 @@ index 00000000000..588887e1d96 + F27, F27_H, +); + -+alloc_class chunk2( -+ V0, V0_H, V0_J, V0_K, -+ V1, V1_H, V1_J, V1_K, -+ V2, V2_H, V2_J, V2_K, -+ V3, V3_H, V3_J, V3_K, -+ V4, V4_H, V4_J, V4_K, -+ V5, V5_H, V5_J, V5_K, -+ V6, V6_H, V6_J, V6_K, -+ V7, V7_H, V7_J, V7_K, -+ V8, V8_H, V8_J, V8_K, -+ V9, V9_H, V9_J, V9_K, -+ V10, V10_H, V10_J, V10_K, -+ V11, V11_H, V11_J, V11_K, -+ V12, V12_H, V12_J, V12_K, -+ V13, V13_H, V13_J, V13_K, -+ V14, V14_H, V14_J, V14_K, -+ V15, V15_H, V15_J, V15_K, -+ V16, V16_H, V16_J, V16_K, -+ V17, V17_H, V17_J, V17_K, -+ V18, V18_H, V18_J, V18_K, -+ V19, V19_H, V19_J, V19_K, -+ V20, V20_H, V20_J, V20_K, -+ V21, V21_H, V21_J, V21_K, -+ V22, V22_H, V22_J, V22_K, -+ V23, V23_H, V23_J, V23_K, -+ V24, V24_H, V24_J, V24_K, -+ V25, V25_H, V25_J, V25_K, -+ V26, V26_H, V26_J, V26_K, -+ V27, V27_H, V27_J, V27_K, -+ V28, V28_H, V28_J, V28_K, -+ V29, V29_H, V29_J, V29_K, -+ V30, V30_H, V30_J, V30_K, -+ V31, V31_H, V31_J, V31_K, -+); -+ -+alloc_class chunk3(RFLAGS); ++alloc_class chunk2(RFLAGS); + +//----------Architecture Description Register Classes-------------------------- +// Several register classes are automatically defined based upon information in +// this architecture description. +// 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) -+// 2) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) ++// 2) reg_class compiler_method_reg ( /* as def'd in frame section */ ) ++// 2) reg_class interpreter_method_reg ( /* as def'd in frame section */ ) ++// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) +// + +// Class for all 32 bit general purpose registers @@ -30670,41 +28352,6 @@ index 00000000000..588887e1d96 + F31, F31_H +); + -+// Class for all RVV vector registers -+reg_class vectora_reg( -+ V1, V1_H, V1_J, V1_K, -+ V2, V2_H, V2_J, V2_K, -+ V3, V3_H, V3_J, V3_K, -+ V4, V4_H, V4_J, V4_K, -+ V5, V5_H, V5_J, V5_K, -+ V6, V6_H, V6_J, V6_K, -+ V7, V7_H, V7_J, V7_K, -+ V8, V8_H, V8_J, V8_K, -+ V9, V9_H, V9_J, V9_K, -+ V10, V10_H, V10_J, V10_K, -+ V11, V11_H, V11_J, V11_K, -+ V12, V12_H, V12_J, V12_K, -+ V13, V13_H, V13_J, V13_K, -+ V14, V14_H, V14_J, V14_K, -+ V15, V15_H, V15_J, V15_K, -+ V16, V16_H, V16_J, V16_K, -+ V17, V17_H, V17_J, V17_K, -+ V18, V18_H, V18_J, V18_K, -+ V19, V19_H, V19_J, V19_K, -+ V20, V20_H, V20_J, V20_K, -+ V21, V21_H, V21_J, V21_K, -+ V22, V22_H, V22_J, V22_K, -+ V23, V23_H, V23_J, V23_K, -+ V24, V24_H, V24_J, V24_K, -+ V25, V25_H, V25_J, V25_K, -+ V26, V26_H, V26_J, V26_K, -+ V27, V27_H, V27_J, V27_K, -+ V28, V28_H, V28_J, V28_K, -+ V29, V29_H, V29_J, V29_K, -+ V30, V30_H, V30_J, V30_K, -+ V31, V31_H, V31_J, V31_K -+); -+ +// Class for 64 bit register f0 +reg_class f0_reg( + F0, F0_H @@ -30725,31 +28372,6 @@ index 00000000000..588887e1d96 + F3, F3_H +); + -+// class for vector register v1 -+reg_class v1_reg( -+ V1, V1_H, V1_J, V1_K -+); -+ -+// class for vector register v2 -+reg_class v2_reg( -+ V2, V2_H, V2_J, V2_K -+); -+ -+// class for vector register v3 -+reg_class v3_reg( -+ V3, V3_H, V3_J, V3_K -+); -+ -+// class for vector register v4 -+reg_class v4_reg( -+ V4, V4_H, V4_J, V4_K -+); -+ -+// class for vector register v5 -+reg_class v5_reg( -+ V5, V5_H, V5_J, V5_K -+); -+ +// class for condition codes +reg_class reg_flags(RFLAGS); +%} @@ -30780,7 +28402,7 @@ index 00000000000..588887e1d96 + int_def LOAD_COST ( 300, 3 * DEFAULT_COST); // load, fpload + int_def STORE_COST ( 100, 1 * DEFAULT_COST); // store, fpstore + int_def XFER_COST ( 300, 3 * DEFAULT_COST); // mfc, mtc, fcvt, fmove, fcmp -+ int_def BRANCH_COST ( 100, 1 * DEFAULT_COST); // branch, jmp, call ++ int_def BRANCH_COST ( 200, 2 * DEFAULT_COST); // branch, jmp, call + int_def IMUL_COST ( 1000, 10 * DEFAULT_COST); // imul + int_def IDIVSI_COST ( 3400, 34 * DEFAULT_COST); // idivdi + int_def IDIVDI_COST ( 6600, 66 * DEFAULT_COST); // idivsi @@ -30848,18 +28470,14 @@ index 00000000000..588887e1d96 + } +}; + -+class Node::PD { -+public: -+ enum NodeFlags { -+ _last_flag = Node::_last_flag -+ }; -+}; -+ +bool is_CAS(int opcode, bool maybe_volatile); + +// predicate controlling translation of CompareAndSwapX +bool needs_acquiring_load_reserved(const Node *load); + ++// predicate controlling translation of StoreCM ++bool unnecessary_storestore(const Node *storecm); ++ +// predicate controlling addressing modes +bool size_fits_all_mem_uses(AddPNode* addp, int shift); +%} @@ -30910,17 +28528,6 @@ index 00000000000..588887e1d96 + } +} + -+void PhaseOutput::pd_perform_mach_node_analysis() { -+} -+ -+int MachNode::pd_alignment_required() const { -+ return 1; -+} -+ -+int MachNode::compute_padding(int current_offset) const { -+ return 0; -+} -+ +// is_CAS(int opcode, bool maybe_volatile) +// +// return true if opcode is one of the possible CompareAndSwapX @@ -30933,8 +28540,10 @@ index 00000000000..588887e1d96 + case Op_CompareAndSwapL: + case Op_CompareAndSwapP: + case Op_CompareAndSwapN: ++#if INCLUDE_SHENANDOAHGC + case Op_ShenandoahCompareAndSwapP: + case Op_ShenandoahCompareAndSwapN: ++#endif + case Op_CompareAndSwapB: + case Op_CompareAndSwapS: + case Op_GetAndSetI: @@ -30956,10 +28565,6 @@ index 00000000000..588887e1d96 + case Op_WeakCompareAndSwapL: + case Op_WeakCompareAndSwapP: + case Op_WeakCompareAndSwapN: -+ case Op_ShenandoahWeakCompareAndSwapP: -+ case Op_ShenandoahWeakCompareAndSwapN: -+ case Op_ShenandoahCompareAndExchangeP: -+ case Op_ShenandoahCompareAndExchangeN: + return maybe_volatile; + default: + return false; @@ -30982,6 +28587,29 @@ index 00000000000..588887e1d96 + // so we can just return true here + return true; +} ++ ++// predicate controlling translation of StoreCM ++// ++// returns true if a StoreStore must precede the card write otherwise ++// false ++ ++bool unnecessary_storestore(const Node *storecm) ++{ ++ assert(storecm->Opcode() == Op_StoreCM, "expecting a StoreCM"); ++ ++ // we need to generate a dmb ishst between an object put and the ++ // associated card mark when we are using CMS without conditional ++ // card marking ++ ++ if (UseConcMarkSweepGC && !UseCondCardMark) { ++ return false; ++ } ++ ++ // a storestore is unnecesary in all other cases ++ ++ return true; ++} ++ +#define __ _masm. + +// advance declarations for helper functions to convert register @@ -31029,11 +28657,6 @@ index 00000000000..588887e1d96 + } +} + -+int MachCallNativeNode::ret_addr_offset() { -+ Unimplemented(); -+ return -1; -+} -+ +// +// Compute padding required for nodes which need alignment +// @@ -31062,6 +28685,20 @@ index 00000000000..588887e1d96 + return align_up(current_offset, alignment_required()) - current_offset; +} + ++// Indicate if the safepoint node needs the polling page as an input ++ ++// the shared code plants the oop data at the start of the generated ++// code for the safepoint node and that needs ot be at the load ++// instruction itself. so we cannot plant a mov of the safepoint poll ++// address followed by a load. setting this to true means the mov is ++// scheduled as a prior instruction. that's better for scheduling ++// anyway. ++ ++bool SafePointNode::needs_polling_address_input() ++{ ++ return true; ++} ++ +//============================================================================= + +#ifndef PRODUCT @@ -31072,7 +28709,7 @@ index 00000000000..588887e1d96 +#endif + +void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + __ ebreak(); +} @@ -31090,7 +28727,7 @@ index 00000000000..588887e1d96 +#endif + + void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const { -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); // nops shall be 2-byte under RVC for alignment purposes. + for (int i = 0; i < _count; i++) { + __ nop(); @@ -31104,7 +28741,7 @@ index 00000000000..588887e1d96 +//============================================================================= +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; + -+int ConstantTable::calculate_table_base_offset() const { ++int Compile::ConstantTable::calculate_table_base_offset() const { + return 0; // absolute addressing, no offset +} + @@ -31133,9 +28770,9 @@ index 00000000000..588887e1d96 + assert_cond(st != NULL && ra_ != NULL); + Compile* C = ra_->C; + -+ int framesize = C->output()->frame_slots() << LogBytesPerInt; ++ int framesize = C->frame_slots() << LogBytesPerInt; + -+ if (C->output()->need_stack_bang(framesize)) { ++ if (C->need_stack_bang(framesize)) { + st->print("# stack bang size=%d\n\t", framesize); + } + @@ -31143,67 +28780,41 @@ index 00000000000..588887e1d96 + st->print("sd ra, [sp, #%d]\n\t", - wordSize); + if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); } + st->print("sub sp, sp, #%d\n\t", framesize); -+ -+ if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { -+ st->print("ld t0, [guard]\n\t"); -+ st->print("membar LoadLoad\n\t"); -+ st->print("ld t1, [xthread, #thread_disarmed_offset]\n\t"); -+ st->print("beq t0, t1, skip\n\t"); -+ st->print("jalr #nmethod_entry_barrier_stub\n\t"); -+ st->print("j skip\n\t"); -+ st->print("guard: int\n\t"); -+ st->print("skip:\n\t"); -+ } +} +#endif + +void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + assert_cond(ra_ != NULL); + Compile* C = ra_->C; -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + + // n.b. frame size includes space for return pc and fp -+ const int framesize = C->output()->frame_size_in_bytes(); ++ const int framesize = C->frame_size_in_bytes(); + + // insert a nop at the start of the prolog so we can patch in a + // branch if we need to invalidate the method later ++ MacroAssembler::assert_alignment(__ pc()); + __ nop(); + + assert_cond(C != NULL); + -+ if (C->clinit_barrier_on_entry()) { -+ assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started"); -+ -+ Label L_skip_barrier; -+ -+ __ mov_metadata(t1, C->method()->holder()->constant_encoding()); -+ __ clinit_barrier(t1, t0, &L_skip_barrier); -+ __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -+ __ bind(L_skip_barrier); -+ } -+ -+ int bangsize = C->output()->bang_size_in_bytes(); -+ if (C->output()->need_stack_bang(bangsize)) { ++ int bangsize = C->bang_size_in_bytes(); ++ if (C->need_stack_bang(bangsize)) { + __ generate_stack_overflow_check(bangsize); + } + + __ build_frame(framesize); + -+ if (C->stub_function() == NULL) { -+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ bs->nmethod_entry_barrier(&_masm); -+ } -+ + if (VerifyStackAtCalls) { + Unimplemented(); + } + -+ C->output()->set_frame_complete(cbuf.insts_size()); ++ C->set_frame_complete(cbuf.insts_size()); + + if (C->has_mach_constant_base_node()) { + // NOTE: We set the table base offset here because users might be + // emitted before MachConstantBaseNode. -+ ConstantTable& constant_table = C->output()->constant_table(); ++ Compile::ConstantTable& constant_table = C->constant_table(); + constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); + } +} @@ -31227,7 +28838,7 @@ index 00000000000..588887e1d96 + assert_cond(st != NULL && ra_ != NULL); + Compile* C = ra_->C; + assert_cond(C != NULL); -+ int framesize = C->output()->frame_size_in_bytes(); ++ int framesize = C->frame_size_in_bytes(); + + st->print("# pop frame %d\n\t", framesize); + @@ -31242,9 +28853,9 @@ index 00000000000..588887e1d96 + } + + if (do_polling() && C->is_method_compilation()) { -+ st->print("# test polling word\n\t"); -+ st->print("ld t0, [xthread,#%d]\n\t", in_bytes(JavaThread::polling_word_offset())); -+ st->print("bgtu sp, t0, #slow_path"); ++ st->print("# touch polling page\n\t"); ++ st->print("li t0, #0x%lx\n\t", p2i(os::get_polling_page())); ++ st->print("ld zr, [t0]"); + } +} +#endif @@ -31252,9 +28863,9 @@ index 00000000000..588887e1d96 +void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { + assert_cond(ra_ != NULL); + Compile* C = ra_->C; -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + assert_cond(C != NULL); -+ int framesize = C->output()->frame_size_in_bytes(); ++ int framesize = C->frame_size_in_bytes(); + + __ remove_frame(framesize); + @@ -31263,13 +28874,7 @@ index 00000000000..588887e1d96 + } + + if (do_polling() && C->is_method_compilation()) { -+ Label dummy_label; -+ Label* code_stub = &dummy_label; -+ if (!C->output()->in_scratch_emit_size()) { -+ code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); -+ } -+ __ relocate(relocInfo::poll_return_type); -+ __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); ++ __ read_polling_page(t0, os::get_polling_page(), relocInfo::poll_return_type); + } +} + @@ -31287,11 +28892,19 @@ index 00000000000..588887e1d96 + return MachNode::pipeline_class(); +} + ++// This method seems to be obsolete. It is declared in machnode.hpp ++// and defined in all *.ad files, but it is never called. Should we ++// get rid of it? ++int MachEpilogNode::safepoint_offset() const { ++ assert(do_polling(), "no return for this epilog node"); ++ return 4; ++} ++ +//============================================================================= + +// Figure out which register class each belongs in: rc_int, rc_float or +// rc_stack. -+enum RC { rc_bad, rc_int, rc_float, rc_vector, rc_stack }; ++enum RC { rc_bad, rc_int, rc_float, rc_stack }; + +static enum RC rc_class(OptoReg::Name reg) { + @@ -31312,13 +28925,7 @@ index 00000000000..588887e1d96 + return rc_float; + } + -+ // we have 32 vector register * 4 halves -+ int slots_of_vector_registers = VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers; -+ if (reg < slots_of_int_registers + slots_of_float_registers + slots_of_vector_registers) { -+ return rc_vector; -+ } -+ -+ // Between vector regs & stack is the flags regs. ++ // Between float regs & stack is the flags regs. + assert(OptoReg::is_stack(reg), "blow up if spilling flags"); + + return rc_stack; @@ -31356,31 +28963,8 @@ index 00000000000..588887e1d96 + int src_offset = ra_->reg2offset(src_lo); + int dst_offset = ra_->reg2offset(dst_lo); + -+ if (bottom_type()->isa_vect() != NULL) { -+ uint ireg = ideal_reg(); -+ if (ireg == Op_VecA && cbuf) { -+ C2_MacroAssembler _masm(cbuf); -+ Assembler::CompressibleRegion cr(&_masm); -+ int vector_reg_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -+ if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { -+ // stack to stack -+ __ spill_copy_vector_stack_to_stack(src_offset, dst_offset, -+ vector_reg_size_in_bytes); -+ } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) { -+ // vpr to stack -+ __ spill(as_VectorRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo)); -+ } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) { -+ // stack to vpr -+ __ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo)); -+ } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) { -+ // vpr to vpr -+ __ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo])); -+ } else { -+ ShouldNotReachHere(); -+ } -+ } -+ } else if (cbuf != NULL) { -+ C2_MacroAssembler _masm(cbuf); ++ if (cbuf != NULL) { ++ MacroAssembler _masm(cbuf); + Assembler::CompressibleRegion cr(&_masm); + switch (src_lo_rc) { + case rc_int: @@ -31463,17 +29047,7 @@ index 00000000000..588887e1d96 + } else { + st->print("%s", Matcher::regName[dst_lo]); + } -+ if (bottom_type()->isa_vect() != NULL) { -+ int vsize = 0; -+ if (ideal_reg() == Op_VecA) { -+ vsize = Matcher::scalable_vector_reg_size(T_BYTE) * 8; -+ } else { -+ ShouldNotReachHere(); -+ } -+ st->print("\t# vector spill size = %d", vsize); -+ } else { -+ st->print("\t# spill size = %d", is64 ? 64 : 32); -+ } ++ st->print("\t# spill size = %d", is64 ? 64 : 32); + } + + return 0; @@ -31510,7 +29084,7 @@ index 00000000000..588887e1d96 +#endif + +void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + + assert_cond(ra_ != NULL); + int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); @@ -31546,7 +29120,7 @@ index 00000000000..588887e1d96 + st->print_cr("# MachUEPNode"); + if (UseCompressedClassPointers) { + st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); -+ if (CompressedKlassPointers::shift() != 0) { ++ if (Universe::narrow_klass_shift() != 0) { + st->print_cr("\tdecode_klass_not_null t0, t0"); + } + } else { @@ -31561,12 +29135,16 @@ index 00000000000..588887e1d96 +void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const +{ + // This is the unverified entry point. -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + + Label skip; + __ cmp_klass(j_rarg0, t1, t0, skip); + __ far_jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); + __ bind(skip); ++ ++ // These NOPs are critical so that verified entry point is properly ++ // 4 bytes aligned for patching by NativeJump::patch_verified_entry() ++ __ align(NativeInstruction::instruction_size); +} + +uint MachUEPNode::size(PhaseRegAlloc* ra_) const @@ -31588,7 +29166,7 @@ index 00000000000..588887e1d96 + // j #exception_blob_entry_point + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_exception_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); @@ -31606,7 +29184,7 @@ index 00000000000..588887e1d96 +{ + // Note that the code buffer's insts_mark is always relative to insts. + // That's why we must use the macroassembler to generate a handler. -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + address base = __ start_a_stub(size_deopt_handler()); + if (base == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); @@ -31632,68 +29210,38 @@ index 00000000000..588887e1d96 + } + + switch (opcode) { -+ case Op_CacheWB: // fall through -+ case Op_CacheWBPreSync: // fall through -+ case Op_CacheWBPostSync: -+ if (!VM_Version::supports_data_cache_line_flush()) { -+ return false; -+ } -+ break; -+ -+ case Op_StrCompressedCopy: // fall through -+ case Op_StrInflatedCopy: // fall through -+ case Op_CountPositives: -+ return UseRVV; -+ -+ case Op_EncodeISOArray: -+ return UseRVV && SpecialEncodeISOArray; -+ + case Op_PopCountI: + case Op_PopCountL: + return UsePopCountInstruction; + -+ case Op_RotateRight: -+ case Op_RotateLeft: + case Op_CountLeadingZerosI: + case Op_CountLeadingZerosL: + case Op_CountTrailingZerosI: + case Op_CountTrailingZerosL: -+ return UseRVB; ++ return UseZbb; + } + + return true; // Per default match rules are supported. +} + +// Identify extra cases that we might want to provide match rules for vector nodes and -+// other intrinsics guarded with vector length (vlen) and element type (bt). -+const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { -+ if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) { -+ return false; -+ } -+ -+ return op_vec_supported(opcode); -+} -+ -+const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { ++// other intrinsics guarded with vector length (vlen). ++const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { + return false; +} + -+const RegMask* Matcher::predicate_reg_mask(void) { -+ return NULL; -+} -+ -+const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { -+ return NULL; -+} -+ -+// Vector calling convention not yet implemented. -+const bool Matcher::supports_vector_calling_convention(void) { ++const bool Matcher::has_predicated_vectors(void) { + return false; +} + -+OptoRegPair Matcher::vector_return_value(uint ideal_reg) { ++const int Matcher::float_pressure(int default_pressure_threshold) { ++ return default_pressure_threshold; ++} ++ ++int Matcher::regnum_to_fpu_offset(int regnum) ++{ + Unimplemented(); -+ return OptoRegPair(0, 0); ++ return 0; +} + +// Is this branch offset short enough that a short branch can be used? @@ -31719,13 +29267,19 @@ index 00000000000..588887e1d96 + return (-4096 <= offs && offs < 4096); +} + ++const bool Matcher::isSimpleConstant64(jlong value) { ++ // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. ++ // Probably always true, even if a temp register is required. ++ return true; ++} ++ ++// true just means we have fast l2f conversion ++const bool Matcher::convL2FSupported(void) { ++ return true; ++} ++ +// Vector width in bytes. +const int Matcher::vector_width_in_bytes(BasicType bt) { -+ if (UseRVV) { -+ // The MaxVectorSize should have been set by detecting RVV max vector register size when check UseRVV. -+ // MaxVectorSize == VM_Version::_initial_vector_length -+ return MaxVectorSize; -+ } + return 0; +} + @@ -31739,34 +29293,108 @@ index 00000000000..588887e1d96 + +// Vector ideal reg. +const uint Matcher::vector_ideal_reg(int len) { -+ assert(MaxVectorSize >= len, ""); -+ if (UseRVV) { -+ return Op_VecA; -+ } -+ + ShouldNotReachHere(); + return 0; +} + -+const int Matcher::scalable_vector_reg_size(const BasicType bt) { -+ return Matcher::max_vector_size(bt); ++const uint Matcher::vector_shift_count_ideal_reg(int size) { ++ fatal("vector shift is not supported"); ++ return Node::NotAMachineReg; +} + -+MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { -+ ShouldNotReachHere(); // generic vector operands not supported -+ return NULL; -+} -+ -+bool Matcher::is_reg2reg_move(MachNode* m) { -+ ShouldNotReachHere(); // generic vector operands not supported ++// AES support not yet implemented ++const bool Matcher::pass_original_key_for_aes() { + return false; +} + -+bool Matcher::is_generic_vector(MachOper* opnd) { -+ ShouldNotReachHere(); // generic vector operands not supported ++// RISC-V supports misaligned vectors store/load. ++const bool Matcher::misaligned_vectors_ok() { ++ return true; ++} ++ ++// false => size gets scaled to BytesPerLong, ok. ++const bool Matcher::init_array_count_is_in_bytes = false; ++ ++// Use conditional move (CMOVL) ++const int Matcher::long_cmove_cost() { ++ // long cmoves are no more expensive than int cmoves ++ return 0; ++} ++ ++const int Matcher::float_cmove_cost() { ++ // float cmoves are no more expensive than int cmoves ++ return 0; ++} ++ ++// Does the CPU require late expand (see block.cpp for description of late expand)? ++const bool Matcher::require_postalloc_expand = false; ++ ++// Do we need to mask the count passed to shift instructions or does ++// the cpu only look at the lower 5/6 bits anyway? ++const bool Matcher::need_masked_shift_count = false; ++ ++// This affects two different things: ++// - how Decode nodes are matched ++// - how ImplicitNullCheck opportunities are recognized ++// If true, the matcher will try to remove all Decodes and match them ++// (as operands) into nodes. NullChecks are not prepared to deal with ++// Decodes by final_graph_reshaping(). ++// If false, final_graph_reshaping() forces the decode behind the Cmp ++// for a NullCheck. The matcher matches the Decode node into a register. ++// Implicit_null_check optimization moves the Decode along with the ++// memory operation back up before the NullCheck. ++bool Matcher::narrow_oop_use_complex_address() { ++ return Universe::narrow_oop_shift() == 0; ++} ++ ++bool Matcher::narrow_klass_use_complex_address() { ++// TODO ++// decide whether we need to set this to true + return false; +} + ++bool Matcher::const_oop_prefer_decode() { ++ // Prefer ConN+DecodeN over ConP in simple compressed oops mode. ++ return Universe::narrow_oop_base() == NULL; ++} ++ ++bool Matcher::const_klass_prefer_decode() { ++ // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. ++ return Universe::narrow_klass_base() == NULL; ++} ++ ++// Is it better to copy float constants, or load them directly from ++// memory? Intel can load a float constant from a direct address, ++// requiring no extra registers. Most RISCs will have to materialize ++// an address into a register first, so they would do better to copy ++// the constant from stack. ++const bool Matcher::rematerialize_float_constants = false; ++ ++// If CPU can load and store mis-aligned doubles directly then no ++// fixup is needed. Else we split the double into 2 integer pieces ++// and move it piece-by-piece. Only happens when passing doubles into ++// C code as the Java calling convention forces doubles to be aligned. ++const bool Matcher::misaligned_doubles_ok = true; ++ ++// No-op on amd64 ++void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { ++ Unimplemented(); ++} ++ ++// Advertise here if the CPU requires explicit rounding operations to ++// implement the UseStrictFP mode. ++const bool Matcher::strict_fp_requires_explicit_rounding = false; ++ ++// Are floats converted to double when stored to stack during ++// deoptimization? ++bool Matcher::float_in_double() { return false; } ++ ++// Do ints take an entire long register or just half? ++// The relevant question is how the int is callee-saved: ++// the whole long is written but de-opt'ing will have to extract ++// the relevant 32 bits. ++const bool Matcher::int_in_long = true; ++ +// Return whether or not this register is ever used as an argument. +// This function is used on startup to build the trampoline stubs in +// generateOptoStub. Registers not mentioned will be killed by the VM @@ -31798,33 +29426,6 @@ index 00000000000..588887e1d96 + return can_be_java_arg(reg); +} + -+uint Matcher::int_pressure_limit() -+{ -+ // A derived pointer is live at CallNode and then is flagged by RA -+ // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip -+ // derived pointers and lastly fail to spill after reaching maximum -+ // number of iterations. Lowering the default pressure threshold to -+ // (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become -+ // a high register pressure area of the code so that split_DEF can -+ // generate DefinitionSpillCopy for the derived pointer. -+ uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1; -+ if (!PreserveFramePointer) { -+ // When PreserveFramePointer is off, frame pointer is allocatable, -+ // but different from other SOC registers, it is excluded from -+ // fatproj's mask because its save type is No-Save. Decrease 1 to -+ // ensure high pressure at fatproj when PreserveFramePointer is off. -+ // See check_pressure_at_fatproj(). -+ default_int_pressure_threshold--; -+ } -+ return (INTPRESSURE == -1) ? default_int_pressure_threshold : INTPRESSURE; -+} -+ -+uint Matcher::float_pressure_limit() -+{ -+ // _FLOAT_REG_mask is generated by adlc from the float_reg register class. -+ return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE; -+} -+ +bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { + return false; +} @@ -31871,23 +29472,18 @@ index 00000000000..588887e1d96 + return true; +} + -+// Should the Matcher clone input 'm' of node 'n'? -+bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { -+ assert_cond(m != NULL); -+ if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) -+ mstack.push(m, Visit); // m = ShiftCntV -+ return true; -+ } -+ return false; -+} ++const bool Matcher::convi2l_type_required = false; + +// Should the Matcher clone shifts on addressing modes, expecting them +// to be subsumed into complex addressing expressions or compute them +// into registers? -+bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { ++bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { + return clone_base_plus_offset_address(m, mstack, address_visited); +} + ++void Compile::reshape_address(AddPNode* addp) { ++} ++ +%} + + @@ -31922,15 +29518,15 @@ index 00000000000..588887e1d96 + // BEGIN Non-volatile memory access + + enc_class riscv_enc_li_imm(iRegIorL dst, immIorL src) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + int64_t con = (int64_t)$src$$constant; + Register dst_reg = as_Register($dst$$reg); -+ __ li(dst_reg, con); ++ __ mv(dst_reg, con); + %} + + enc_class riscv_enc_mov_p(iRegP dst, immP src) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL || con == (address)1) { @@ -31943,25 +29539,36 @@ index 00000000000..588887e1d96 + __ mov_metadata(dst_reg, (Metadata*)con); + } else { + assert(rtype == relocInfo::none, "unexpected reloc type"); -+ __ li(dst_reg, $src$$constant); ++ __ mv(dst_reg, $src$$constant); + } + } + %} + + enc_class riscv_enc_mov_p1(iRegP dst) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register dst_reg = as_Register($dst$$reg); -+ __ li(dst_reg, 1); ++ __ mv(dst_reg, 1); ++ %} ++ ++ enc_class riscv_enc_mov_poll_page(iRegP dst, immPollPage src) %{ ++ MacroAssembler _masm(&cbuf); ++ int32_t offset = 0; ++ address page = (address)$src$$constant; ++ unsigned long align = (unsigned long)page & 0xfff; ++ assert(align == 0, "polling page must be page aligned"); ++ Register dst_reg = as_Register($dst$$reg); ++ __ la_patchable(dst_reg, Address(page, relocInfo::poll_type), offset); ++ __ addi(dst_reg, dst_reg, offset); + %} + + enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + __ load_byte_map_base($dst$$Register); + %} + + enc_class riscv_enc_mov_n(iRegN dst, immN src) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL) { @@ -31974,13 +29581,13 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_mov_zero(iRegNorP dst) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + __ mv(dst_reg, zr); + %} + + enc_class riscv_enc_mov_nk(iRegN dst, immNKlass src) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + address con = (address)$src$$constant; + if (con == NULL) { @@ -31992,43 +29599,43 @@ index 00000000000..588887e1d96 + } + %} + -+ enc_class riscv_enc_cmpxchgw(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchgw(iRegINoSp res, memory mem, iRegI oldval, iRegI newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + -+ enc_class riscv_enc_cmpxchgn(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchgn(iRegINoSp res, memory mem, iRegI oldval, iRegI newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + -+ enc_class riscv_enc_cmpxchg(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchg(iRegINoSp res, memory mem, iRegL oldval, iRegL newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + -+ enc_class riscv_enc_cmpxchgw_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchgw_acq(iRegINoSp res, memory mem, iRegI oldval, iRegI newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + -+ enc_class riscv_enc_cmpxchgn_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchgn_acq(iRegINoSp res, memory mem, iRegI oldval, iRegI newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); + %} + -+ enc_class riscv_enc_cmpxchg_acq(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_cmpxchg_acq(iRegINoSp res, memory mem, iRegL oldval, iRegL newval) %{ ++ MacroAssembler _masm(&cbuf); + __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + /*result as bool*/ true); @@ -32037,13 +29644,13 @@ index 00000000000..588887e1d96 + // compare and branch instruction encodings + + enc_class riscv_enc_j(label lbl) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Label* L = $lbl$$label; + __ j(*L); + %} + + enc_class riscv_enc_far_cmpULtGe_imm0_branch(cmpOpULtGe cmp, iRegIorL op1, label lbl) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Label* L = $lbl$$label; + switch ($cmp$$cmpcode) { + case(BoolTest::ge): @@ -32067,7 +29674,7 @@ index 00000000000..588887e1d96 + + Label miss; + Label done; -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + __ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg, + NULL, &miss); + if ($primary) { @@ -32079,14 +29686,14 @@ index 00000000000..588887e1d96 + + __ bind(miss); + if (!$primary) { -+ __ li(cr_reg, 1); ++ __ mv(cr_reg, 1); + } + + __ bind(done); + %} + + enc_class riscv_enc_java_static_call(method meth) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + + address addr = (address)$meth$$method; + address call = NULL; @@ -32118,7 +29725,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_java_dynamic_call(method meth) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + int method_index = resolved_method_index(cbuf); + address call = __ ic_call((address)$meth$$method, method_index); + if (call == NULL) { @@ -32128,7 +29735,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_call_epilog() %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + if (VerifyStackAtCalls) { + // Check that stack depth is unchanged: find majik cookie on stack + __ call_Unimplemented(); @@ -32136,7 +29743,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_java_to_runtime(method meth) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + + // some calls to generated routines (arraycopy code) are scheduled + // by C2 as runtime calls. if so we can call them using a jr (they @@ -32164,8 +29771,8 @@ index 00000000000..588887e1d96 + %} + + // using the cr register as the bool result: 0 for success; others failed. -+ enc_class riscv_enc_fast_lock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_fast_lock(iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2) %{ ++ MacroAssembler _masm(&cbuf); + Register flag = t1; + Register oop = as_Register($object$$reg); + Register box = as_Register($box$$reg); @@ -32179,87 +29786,80 @@ index 00000000000..588887e1d96 + // Load markWord from object into displaced_header. + __ ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes())); + -+ if (DiagnoseSyncOnValueBasedClasses != 0) { -+ __ load_klass(flag, oop); -+ __ lwu(flag, Address(flag, Klass::access_flags_offset())); -+ __ andi(flag, flag, JVM_ACC_IS_VALUE_BASED_CLASS, tmp /* tmp */); -+ __ bnez(flag, cont, true /* is_far */); ++ // Always do locking in runtime. ++ if (EmitSync & 0x01) { ++ __ mv(flag, 1); ++ return; ++ } ++ ++ if (UseBiasedLocking && !UseOptoBiasInlining) { ++ __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont, /*slow_case*/NULL, NULL, flag); + } + + // Check for existing monitor -+ __ andi(t0, disp_hdr, markWord::monitor_value); -+ __ bnez(t0, object_has_monitor); -+ -+ if (!UseHeavyMonitors) { -+ // Set tmp to be (markWord of object | UNLOCK_VALUE). -+ __ ori(tmp, disp_hdr, markWord::unlocked_value); -+ -+ // Initialize the box. (Must happen before we update the object mark!) -+ __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ -+ // Compare object markWord with an unlocked value (tmp) and if -+ // equal exchange the stack address of our box with object markWord. -+ // On failure disp_hdr contains the possibly locked markWord. -+ __ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq, -+ Assembler::rl, /*result*/disp_hdr); -+ __ mv(flag, zr); -+ __ beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas -+ -+ assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); -+ -+ // If the compare-and-exchange succeeded, then we found an unlocked -+ // object, will have now locked it will continue at label cont -+ // We did not see an unlocked object so try the fast recursive case. -+ -+ // Check if the owner is self by comparing the value in the -+ // markWord of object (disp_hdr) with the stack pointer. -+ __ sub(disp_hdr, disp_hdr, sp); -+ __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markWord::lock_mask_in_place)); -+ // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, -+ // hence we can store 0 as the displaced header in the box, which indicates that it is a -+ // recursive lock. -+ __ andr(tmp/*==0?*/, disp_hdr, tmp); -+ __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ __ mv(flag, tmp); // we can use the value of tmp as the result here -+ } else { -+ __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow-path ++ if ((EmitSync & 0x02) == 0) { ++ __ andi(t0, disp_hdr, markOopDesc::monitor_value); ++ __ bnez(t0, object_has_monitor); + } + -+ __ j(cont); ++ // Set tmp to be (markWord of object | UNLOCK_VALUE). ++ __ ori(tmp, disp_hdr, markOopDesc::unlocked_value); + -+ // Handle existing monitor. -+ __ bind(object_has_monitor); -+ // The object's monitor m is unlocked iff m->owner == NULL, -+ // otherwise m->owner may contain a thread or a stack address. -+ // -+ // Try to CAS m->owner from NULL to current thread. -+ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markWord::monitor_value)); -+ __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, -+ Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) -+ -+ // Store a non-null value into the box to avoid looking like a re-entrant -+ // lock. The fast-path monitor unlock code checks for -+ // markWord::monitor_value so use markWord::unused_mark which has the -+ // relevant bit set, and also matches ObjectSynchronizer::slow_enter. -+ __ mv(tmp, (address)markWord::unused_mark().value()); ++ // Initialize the box. (Must happen before we update the object mark!) + __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); + -+ __ beqz(flag, cont); // CAS success means locking succeeded -+ -+ __ bne(flag, xthread, cont); // Check for recursive locking -+ -+ // Recursive lock case ++ // Compare object markWord with an unlocked value (tmp) and if ++ // equal exchange the stack address of our box with object markWord. ++ // On failure disp_hdr contains the possibly locked markWord. ++ __ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq, ++ Assembler::rl, /*result*/disp_hdr); + __ mv(flag, zr); -+ __ ld(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); -+ __ add(tmp, tmp, 1u); -+ __ sd(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); ++ __ beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas ++ ++ assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); ++ ++ // If the compare-and-exchange succeeded, then we found an unlocked ++ // object, will have now locked it will continue at label cont ++ // We did not see an unlocked object so try the fast recursive case. ++ ++ // Check if the owner is self by comparing the value in the ++ // markWord of object (disp_hdr) with the stack pointer. ++ __ sub(disp_hdr, disp_hdr, sp); ++ __ mv(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markOopDesc::lock_mask_in_place)); ++ // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, ++ // hence we can store 0 as the displaced header in the box, which indicates that it is a ++ // recursive lock. ++ __ andr(tmp/*==0?*/, disp_hdr, tmp); ++ __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); ++ __ mv(flag, tmp); // we can use the value of tmp as the result here ++ ++ if ((EmitSync & 0x02) == 0) { ++ __ j(cont); ++ ++ // Handle existing monitor. ++ __ bind(object_has_monitor); ++ // The object's monitor m is unlocked iff m->owner == NULL, ++ // otherwise m->owner may contain a thread or a stack address. ++ // ++ // Try to CAS m->owner from NULL to current thread. ++ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value)); ++ __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, ++ Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) ++ ++ // Store a non-null value into the box to avoid looking like a re-entrant ++ // lock. The fast-path monitor unlock code checks for ++ // markOopDesc::monitor_value so use markOopDesc::unused_mark which has the ++ // relevant bit set, and also matches ObjectSynchronizer::slow_enter. ++ __ mv(tmp, (address)markOopDesc::unused_mark()); ++ __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); ++ } + + __ bind(cont); + %} + + // using cr flag to indicate the fast_unlock result: 0 for success; others failed. -+ enc_class riscv_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ enc_class riscv_enc_fast_unlock(iRegP object, iRegP box, iRegPNoSp tmp1, iRegPNoSp tmp2) %{ ++ MacroAssembler _masm(&cbuf); + Register flag = t1; + Register oop = as_Register($object$$reg); + Register box = as_Register($box$$reg); @@ -32270,59 +29870,61 @@ index 00000000000..588887e1d96 + + assert_different_registers(oop, box, tmp, disp_hdr, flag); + -+ if (!UseHeavyMonitors) { -+ // Find the lock address and load the displaced header from the stack. -+ __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ -+ // If the displaced header is 0, we have a recursive unlock. -+ __ mv(flag, disp_hdr); -+ __ beqz(disp_hdr, cont); ++ // Always do locking in runtime. ++ if (EmitSync & 0x01) { ++ __ mv(flag, 1); ++ return; + } + ++ if (UseBiasedLocking && !UseOptoBiasInlining) { ++ __ biased_locking_exit(oop, tmp, cont, flag); ++ } ++ ++ // Find the lock address and load the displaced header from the stack. ++ __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); ++ ++ // If the displaced header is 0, we have a recursive unlock. ++ __ mv(flag, disp_hdr); ++ __ beqz(disp_hdr, cont); ++ + // Handle existing monitor. -+ __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); -+ __ andi(t0, disp_hdr, markWord::monitor_value); -+ __ bnez(t0, object_has_monitor); -+ -+ if (!UseHeavyMonitors) { -+ // Check if it is still a light weight lock, this is true if we -+ // see the stack address of the basicLock in the markWord of the -+ // object. -+ -+ __ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed, -+ Assembler::rl, /*result*/tmp); -+ __ xorr(flag, box, tmp); // box == tmp if cas succeeds -+ } else { -+ __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow path ++ if ((EmitSync & 0x02) == 0) { ++ __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); ++ __ andi(t0, tmp, markOopDesc::monitor_value); ++ __ bnez(t0, object_has_monitor); + } ++ ++ // Check if it is still a light weight lock, this is true if we ++ // see the stack address of the basicLock in the markWord of the ++ // object. ++ ++ __ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed, ++ Assembler::rl, /*result*/tmp); ++ __ xorr(flag, box, tmp); // box == tmp if cas succeeds + __ j(cont); + + assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); + + // Handle existing monitor. -+ __ bind(object_has_monitor); -+ STATIC_ASSERT(markWord::monitor_value <= INT_MAX); -+ __ add(tmp, tmp, -(int)markWord::monitor_value); // monitor -+ __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); ++ if ((EmitSync & 0x02) == 0) { ++ __ bind(object_has_monitor); ++ STATIC_ASSERT(markOopDesc::monitor_value <= INT_MAX); ++ __ add(tmp, tmp, -(int)markOopDesc::monitor_value); // monitor ++ __ ld(flag, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); ++ __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); ++ __ xorr(flag, flag, xthread); // Will be 0 if we are the owner. ++ __ orr(flag, flag, disp_hdr); // Will be 0 if there are 0 recursions ++ __ bnez(flag, cont); + -+ Label notRecursive; -+ __ beqz(disp_hdr, notRecursive); // Will be 0 if not recursive. -+ -+ // Recursive lock -+ __ addi(disp_hdr, disp_hdr, -1); -+ __ sd(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); -+ __ mv(flag, zr); -+ __ j(cont); -+ -+ __ bind(notRecursive); -+ __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); -+ __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); -+ __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. -+ __ bnez(flag, cont); -+ // need a release store here -+ __ la(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); -+ __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); -+ __ sd(zr, Address(tmp)); // set unowned ++ __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); ++ __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); ++ __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. ++ __ bnez(flag, cont); ++ // need a release store here ++ __ la(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); ++ __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); ++ __ sd(zr, Address(tmp)); // set unowned ++ } + + __ bind(cont); + %} @@ -32330,7 +29932,7 @@ index 00000000000..588887e1d96 + // arithmetic encodings + + enc_class riscv_enc_divw(iRegI dst, iRegI src1, iRegI src2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); @@ -32338,7 +29940,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_div(iRegI dst, iRegI src1, iRegI src2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); @@ -32346,7 +29948,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_modw(iRegI dst, iRegI src1, iRegI src2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); @@ -32354,7 +29956,7 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_mod(iRegI dst, iRegI src1, iRegI src2) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Register dst_reg = as_Register($dst$$reg); + Register src1_reg = as_Register($src1$$reg); + Register src2_reg = as_Register($src2$$reg); @@ -32362,14 +29964,14 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_tail_call(iRegP jump_target) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register target_reg = as_Register($jump_target$$reg); + __ jr(target_reg); + %} + + enc_class riscv_enc_tail_jmp(iRegP jump_target) %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + Register target_reg = as_Register($jump_target$$reg); + // exception oop should be in x10 @@ -32380,12 +29982,12 @@ index 00000000000..588887e1d96 + %} + + enc_class riscv_enc_rethrow() %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + __ far_jump(RuntimeAddress(OptoRuntime::rethrow_stub())); + %} + + enc_class riscv_enc_ret() %{ -+ C2_MacroAssembler _masm(&cbuf); ++ MacroAssembler _masm(&cbuf); + Assembler::CompressibleRegion cr(&_masm); + __ ret(); + %} @@ -32451,12 +30053,18 @@ index 00000000000..588887e1d96 +// SP meets the minimum alignment. + +frame %{ ++ // What direction does stack grow in (assumed to be same for C & Java) ++ stack_direction(TOWARDS_LOW); ++ + // These three registers define part of the calling convention + // between compiled code and the interpreter. + + // Inline Cache Register or methodOop for I2C. + inline_cache_reg(R31); + ++ // Method Oop Register when calling interpreter. ++ interpreter_method_oop_reg(R31); ++ + // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] + cisc_spilling_operand_name(indOffset); + @@ -32476,6 +30084,12 @@ index 00000000000..588887e1d96 + // Stack alignment requirement + stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) + ++ // Number of stack slots between incoming argument block and the start of ++ // a new frame. The PROLOG must add this many slots to the stack. The ++ // EPILOG must remove this many slots. RISC-V needs two slots for ++ // return address and fp. ++ in_preserve_stack_slots(2 * VMRegImpl::slots_per_word); ++ + // Number of outgoing stack slots killed above the out_preserve_stack_slots + // for calls to C. Supports the var-args backing area for register parms. + varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes / BytesPerInt); @@ -32494,6 +30108,25 @@ index 00000000000..588887e1d96 + Compile::current()->fixed_slots()), + stack_alignment_in_slots())); + ++ // Body of function which returns an integer array locating ++ // arguments either in registers or in stack slots. Passed an array ++ // of ideal registers called "sig" and a "length" count. Stack-slot ++ // offsets are based on outgoing arguments, i.e. a CALLER setting up ++ // arguments for a CALLEE. Incoming stack arguments are ++ // automatically biased by the preserve_stack_slots field above. ++ ++ calling_convention ++ %{ ++ // No difference between ingoing/outgoing just pass false ++ SharedRuntime::java_calling_convention(sig_bt, regs, length, false); ++ %} ++ ++ c_calling_convention ++ %{ ++ // This is obviously always outgoing ++ (void) SharedRuntime::c_calling_convention(sig_bt, regs, NULL, length); ++ %} ++ + // Location of compiled Java return values. Same as C for now. + return_value + %{ @@ -32750,13 +30383,23 @@ index 00000000000..588887e1d96 + interface(CONST_INTER); +%} + ++// Polling Page Pointer Immediate ++operand immPollPage() ++%{ ++ predicate((address)n->get_ptr() == os::get_polling_page()); ++ match(ConP); ++ ++ op_cost(0); ++ format %{ %} ++ interface(CONST_INTER); ++%} ++ +// Card Table Byte Map Base +operand immByteMapBase() +%{ + // Get base of card map + predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && -+ (CardTable::CardValue*)n->get_ptr() == -+ ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); ++ (jbyte*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); + match(ConP); + + op_cost(0); @@ -32774,6 +30417,14 @@ index 00000000000..588887e1d96 + interface(CONST_INTER); +%} + ++operand immIpowerOf2() %{ ++ predicate(is_power_of_2((juint)(n->get_int()))); ++ match(ConI); ++ op_cost(0); ++ format %{ %} ++ interface(CONST_INTER); ++%} ++ +// Long Immediate: low 32-bit mask +operand immL_32bits() +%{ @@ -33228,67 +30879,6 @@ index 00000000000..588887e1d96 + interface(REG_INTER); +%} + -+// Generic vector class. This will be used for -+// all vector operands. -+operand vReg() -+%{ -+ constraint(ALLOC_IN_RC(vectora_reg)); -+ match(VecA); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand vReg_V1() -+%{ -+ constraint(ALLOC_IN_RC(v1_reg)); -+ match(VecA); -+ match(vReg); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand vReg_V2() -+%{ -+ constraint(ALLOC_IN_RC(v2_reg)); -+ match(VecA); -+ match(vReg); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand vReg_V3() -+%{ -+ constraint(ALLOC_IN_RC(v3_reg)); -+ match(VecA); -+ match(vReg); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand vReg_V4() -+%{ -+ constraint(ALLOC_IN_RC(v4_reg)); -+ match(VecA); -+ match(vReg); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ -+operand vReg_V5() -+%{ -+ constraint(ALLOC_IN_RC(v5_reg)); -+ match(VecA); -+ match(vReg); -+ op_cost(0); -+ format %{ %} -+ interface(REG_INTER); -+%} -+ +// Java Thread Register +operand javaThread_RegP(iRegP reg) +%{ @@ -33346,7 +30936,7 @@ index 00000000000..588887e1d96 + +operand indirectN(iRegN reg) +%{ -+ predicate(CompressedOops::shift() == 0); ++ predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(DecodeN reg); + op_cost(0); @@ -33361,7 +30951,7 @@ index 00000000000..588887e1d96 + +operand indOffIN(iRegN reg, immIOffset off) +%{ -+ predicate(CompressedOops::shift() == 0); ++ predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + op_cost(0); @@ -33376,7 +30966,7 @@ index 00000000000..588887e1d96 + +operand indOffLN(iRegN reg, immLOffset off) +%{ -+ predicate(CompressedOops::shift() == 0); ++ predicate(Universe::narrow_oop_shift() == 0); + constraint(ALLOC_IN_RC(ptr_reg)); + match(AddP (DecodeN reg) off); + op_cost(0); @@ -33569,13 +31159,13 @@ index 00000000000..588887e1d96 + format %{ "" %} + interface(COND_INTER) %{ + equal(0x0, "eq"); -+ greater(0x1, "gt"); ++ greater(0x1, "gtu"); + overflow(0x2, "overflow"); -+ less(0x3, "lt"); ++ less(0x3, "ltu"); + not_equal(0x4, "ne"); -+ less_equal(0x5, "le"); ++ less_equal(0x5, "leu"); + no_overflow(0x6, "no_overflow"); -+ greater_equal(0x7, "ge"); ++ greater_equal(0x7, "geu"); + %} +%} + @@ -33591,13 +31181,13 @@ index 00000000000..588887e1d96 + format %{ "" %} + interface(COND_INTER) %{ + equal(0x0, "eq"); -+ greater(0x1, "gt"); ++ greater(0x1, "gtu"); + overflow(0x2, "overflow"); -+ less(0x3, "lt"); ++ less(0x3, "ltu"); + not_equal(0x4, "ne"); -+ less_equal(0x5, "le"); ++ less_equal(0x5, "leu"); + no_overflow(0x6, "no_overflow"); -+ greater_equal(0x7, "ge"); ++ greater_equal(0x7, "geu"); + %} +%} + @@ -34081,7 +31671,7 @@ index 00000000000..588887e1d96 + LDST : MEM; +%} + -+//------- Store pipeline operations ----------------------- ++//------- Control transfer pipeline operations ------------ + +// Store - zr, mem +// E.g. SD zr, mem @@ -34444,7 +32034,6 @@ index 00000000000..588887e1d96 +instruct loadP(iRegPNoSp dst, memory mem) +%{ + match(Set dst (LoadP mem)); -+ predicate(n->as_Load()->barrier_data() == 0); + + ins_cost(LOAD_COST); + format %{ "ld $dst, $mem\t# ptr, #@loadP" %} @@ -34599,6 +32188,19 @@ index 00000000000..588887e1d96 + ins_pipe(ialu_imm); +%} + ++// Load Poll Page Constant ++instruct loadConPollPage(iRegPNoSp dst, immPollPage con) ++%{ ++ match(Set dst con); ++ ++ ins_cost(ALU_COST * 6); ++ format %{ "movptr $dst, $con\t# Poll Page Ptr, #@loadConPollPage" %} ++ ++ ins_encode(riscv_enc_mov_poll_page(dst, con)); ++ ++ ins_pipe(ialu_imm); ++%} ++ +// Load Byte Map Base Constant +instruct loadByteMapBase(iRegPNoSp dst, immByteMapBase con) +%{ @@ -34715,6 +32317,7 @@ index 00000000000..588887e1d96 +instruct storeimmCM0(immI0 zero, memory mem) +%{ + match(Set mem (StoreCM mem zero)); ++ predicate(unnecessary_storestore(n)); + + ins_cost(STORE_COST); + format %{ "storestore (elided)\n\t" @@ -34914,6 +32517,8 @@ index 00000000000..588887e1d96 +instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem) +%{ + match(Set mem (StoreN mem zero)); ++ predicate(Universe::narrow_oop_base() == NULL && ++ Universe::narrow_klass_base() == NULL); + + ins_cost(STORE_COST); + format %{ "sw rheapbase, $mem\t# compressed ptr (rheapbase==0), #@storeImmN0" %} @@ -35036,7 +32641,11 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_serial); +%} + -+instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) ++// storeLConditional is used by PhaseMacroExpand::expand_lock_node ++// when attempting to rebias a lock towards the current thread. We ++// must use the acquire form of cmpxchg in order to guarantee acquire ++// semantics in this case. ++instruct storeLConditional(indirect mem, iRegL oldval, iRegL newval, rFlagsReg cr) +%{ + match(Set cr (StoreLConditional mem (Binary oldval newval))); + @@ -35058,7 +32667,7 @@ index 00000000000..588887e1d96 + +// storeIConditional also has acquire semantics, for no better reason +// than matching storeLConditional. -+instruct storeIConditional(indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) ++instruct storeIConditional(indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) +%{ + match(Set cr (StoreIConditional mem (Binary oldval newval))); + @@ -35081,7 +32690,7 @@ index 00000000000..588887e1d96 +// standard CompareAndSwapX when we are using barriers +// these have higher priority than the rules selected by a predicate +instruct compareAndSwapB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndSwapB mem (Binary oldval newval))); + @@ -35104,7 +32713,7 @@ index 00000000000..588887e1d96 +%} + +instruct compareAndSwapS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndSwapS mem (Binary oldval newval))); + @@ -35126,7 +32735,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval) ++instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + match(Set res (CompareAndSwapI mem (Binary oldval newval))); + @@ -35142,7 +32751,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval) ++instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + match(Set res (CompareAndSwapL mem (Binary oldval newval))); + @@ -35160,8 +32769,6 @@ index 00000000000..588887e1d96 + +instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(n->as_LoadStore()->barrier_data() == 0); -+ + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); @@ -35176,7 +32783,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval) ++instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + match(Set res (CompareAndSwapN mem (Binary oldval newval))); + @@ -35194,7 +32801,7 @@ index 00000000000..588887e1d96 + +// alternative CompareAndSwapX when we are eliding barriers +instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35219,7 +32826,7 @@ index 00000000000..588887e1d96 +%} + +instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35243,7 +32850,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval) ++instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35261,7 +32868,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoSp newval) ++instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35281,7 +32888,7 @@ index 00000000000..588887e1d96 + +instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); ++ predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndSwapP mem (Binary oldval newval))); + @@ -35297,7 +32904,7 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_slow); +%} + -+instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegNNoSp oldval, iRegNNoSp newval) ++instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35322,7 +32929,7 @@ index 00000000000..588887e1d96 +// can't check the type of memory ordering here, so we always emit a +// sc_d(w) with rl bit set. +instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndExchangeB mem (Binary oldval newval))); + @@ -35344,7 +32951,7 @@ index 00000000000..588887e1d96 +%} + +instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (CompareAndExchangeS mem (Binary oldval newval))); + @@ -35427,7 +33034,6 @@ index 00000000000..588887e1d96 + +instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); @@ -35447,7 +33053,7 @@ index 00000000000..588887e1d96 +%} + +instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35471,7 +33077,7 @@ index 00000000000..588887e1d96 +%} + +instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35562,7 +33168,7 @@ index 00000000000..588887e1d96 + +instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); ++ predicate(needs_acquiring_load_reserved(n)); + + match(Set res (CompareAndExchangeP mem (Binary oldval newval))); + @@ -35583,7 +33189,7 @@ index 00000000000..588887e1d96 +%} + +instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (WeakCompareAndSwapB mem (Binary oldval newval))); + @@ -35593,21 +33199,20 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapB" ++ "# $res == 1 when success, #@weakCompareAndSwapB" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + match(Set res (WeakCompareAndSwapS mem (Binary oldval newval))); + @@ -35617,14 +33222,13 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapS" ++ "# $res == 1 when success, #@weakCompareAndSwapS" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35638,13 +33242,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapI" ++ "# $res == 1 when success, #@weakCompareAndSwapI" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35658,13 +33261,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapL" ++ "# $res == 1 when success, #@weakCompareAndSwapL" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35678,13 +33280,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapN" ++ "# $res == 1 when success, #@weakCompareAndSwapN" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35692,27 +33293,25 @@ index 00000000000..588887e1d96 + +instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + + ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); + + format %{ + "cmpxchg_weak $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapP" ++ "# $res == 1 when success, #@weakCompareAndSwapP" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35724,21 +33323,20 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapBAcq" ++ "# $res == 1 when success, #@weakCompareAndSwapBAcq" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int8, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); +%} + +instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI_R12 oldval, iRegI_R13 newval, -+ iRegI tmp1, iRegI tmp2, iRegI tmp3, rFlagsReg cr) ++ iRegINoSp tmp1, iRegINoSp tmp2, iRegINoSp tmp3, rFlagsReg cr) +%{ + predicate(needs_acquiring_load_reserved(n)); + @@ -35750,14 +33348,13 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapSAcq" ++ "# $res == 1 when success, #@weakCompareAndSwapSAcq" + %} + + ins_encode %{ + __ weak_cmpxchg_narrow_value(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int16, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, + $tmp1$$Register, $tmp2$$Register, $tmp3$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35773,13 +33370,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapIAcq" ++ "# $res == 1 when success, #@weakCompareAndSwapIAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35795,13 +33391,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapLAcq" ++ "# $res == 1 when success, #@weakCompareAndSwapLAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35817,13 +33412,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapNAcq" ++ "# $res == 1 when success, #@weakCompareAndSwapNAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35831,7 +33425,7 @@ index 00000000000..588887e1d96 + +instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) +%{ -+ predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); ++ predicate(needs_acquiring_load_reserved(n)); + + match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); + @@ -35839,13 +33433,12 @@ index 00000000000..588887e1d96 + + format %{ + "cmpxchg_weak_acq $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval\n\t" -+ "xori $res, $res, 1\t# $res == 1 when success, #@weakCompareAndSwapPAcq" ++ "\t# $res == 1 when success, #@weakCompareAndSwapPAcq" + %} + + ins_encode %{ + __ cmpxchg_weak(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, + /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register); -+ __ xori($res$$Register, $res$$Register, 1); + %} + + ins_pipe(pipe_slow); @@ -35898,7 +33491,6 @@ index 00000000000..588887e1d96 + +instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) +%{ -+ predicate(n->as_LoadStore()->barrier_data() == 0); + match(Set prev (GetAndSetP mem newv)); + + ins_cost(ALU_COST); @@ -35965,7 +33557,7 @@ index 00000000000..588887e1d96 + +instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev) +%{ -+ predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); ++ predicate(needs_acquiring_load_reserved(n)); + + match(Set prev (GetAndSetP mem newv)); + @@ -37285,7 +34877,7 @@ index 00000000000..588887e1d96 +%} + +instruct sqrtF_reg(fRegF dst, fRegF src) %{ -+ match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); ++ match(Set dst (SqrtF src)); + + ins_cost(FSQRT_COST); + format %{ "fsqrt.s $dst, $src\t#@sqrtF_reg" %} @@ -37643,7 +35235,6 @@ index 00000000000..588887e1d96 + +instruct membar_storestore() %{ + match(MemBarStoreStore); -+ match(StoreStoreFence); + ins_cost(ALU_COST); + + format %{ "MEMBAR-store-store\t#@membar_storestore" %} @@ -37728,17 +35319,6 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_class_empty); +%} + -+instruct castLL(iRegL dst) -+%{ -+ match(Set dst (CastLL dst)); -+ -+ size(0); -+ format %{ "# castLL of $dst, #@castLL" %} -+ ins_encode(/* empty encoding */); -+ ins_cost(0); -+ ins_pipe(pipe_class_empty); -+%} -+ +instruct castII(iRegI dst) +%{ + match(Set dst (CastII dst)); @@ -37761,39 +35341,6 @@ index 00000000000..588887e1d96 + ins_pipe(pipe_class_empty); +%} + -+instruct castFF(fRegF dst) -+%{ -+ match(Set dst (CastFF dst)); -+ -+ size(0); -+ format %{ "# castFF of $dst" %} -+ ins_encode(/* empty encoding */); -+ ins_cost(0); -+ ins_pipe(pipe_class_empty); -+%} -+ -+instruct castDD(fRegD dst) -+%{ -+ match(Set dst (CastDD dst)); -+ -+ size(0); -+ format %{ "# castDD of $dst" %} -+ ins_encode(/* empty encoding */); -+ ins_cost(0); -+ ins_pipe(pipe_class_empty); -+%} -+ -+instruct castVV(vReg dst) -+%{ -+ match(Set dst (CastVV dst)); -+ -+ size(0); -+ format %{ "# castVV of $dst" %} -+ ins_encode(/* empty encoding */); -+ ins_cost(0); -+ ins_pipe(pipe_class_empty); -+%} -+ +// ============================================================================ +// Convert Instructions + @@ -38029,7 +35576,7 @@ index 00000000000..588887e1d96 +// in case of 32bit oops (heap < 4Gb). +instruct convN2I(iRegINoSp dst, iRegN src) +%{ -+ predicate(CompressedOops::shift() == 0); ++ predicate(Universe::narrow_oop_shift() == 0); + match(Set dst (ConvL2I (CastP2X (DecodeN src)))); + + ins_cost(ALU_COST); @@ -38588,7 +36135,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38608,7 +36155,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38667,7 +36214,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38686,7 +36233,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38707,7 +36254,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38727,7 +36274,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38748,7 +36295,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38768,7 +36315,7 @@ index 00000000000..588887e1d96 + format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label)); + %} + @@ -38785,7 +36332,7 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); -+ format %{ "float_b$cmp $op1, $op2 \t#@cmpF_branch"%} ++ format %{ "float_b$cmp $op1, $op2, $lbl \t#@cmpF_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); @@ -38802,7 +36349,7 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); -+ format %{ "float_b$cmp $op1, $op2\t#@cmpF_loop"%} ++ format %{ "float_b$cmp $op1, $op2, $lbl\t#@cmpF_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); @@ -38820,10 +36367,10 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); -+ format %{ "double_b$cmp $op1, $op2\t#@cmpD_branch"%} ++ format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_branch"%} + + ins_encode %{ -+ __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), ++ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + @@ -38838,10 +36385,10 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST); -+ format %{ "double_b$cmp $op1, $op2\t#@cmpD_loop"%} ++ format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_loop"%} + + ins_encode %{ -+ __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), ++ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label)); + %} + @@ -39113,7 +36660,7 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(BRANCH_COST); -+ format %{ "far_b$cmp $cr, zr, L\t#@far_cmpFlag_branch"%} ++ format %{ "far_b$cmp $cr, zr, $lbl\t#@far_cmpFlag_branch"%} + + ins_encode %{ + __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label), /* is_far */ true); @@ -39162,7 +36709,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39177,7 +36724,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39220,7 +36767,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39235,7 +36782,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39253,7 +36800,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39271,7 +36818,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39289,7 +36836,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_branch" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39307,7 +36854,7 @@ index 00000000000..588887e1d96 + format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_loop" %} + + ins_encode %{ -+ __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), ++ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), + as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39322,7 +36869,7 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); -+ format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_branch"%} ++ format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_branch"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), @@ -39338,7 +36885,7 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); -+ format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_loop"%} ++ format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_loop"%} + + ins_encode %{ + __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), @@ -39355,10 +36902,10 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); -+ format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_branch"%} ++ format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_branch"%} + + ins_encode %{ -+ __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), ++ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39371,10 +36918,10 @@ index 00000000000..588887e1d96 + effect(USE lbl); + + ins_cost(XFER_COST + BRANCH_COST * 2); -+ format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_loop"%} ++ format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_loop"%} + + ins_encode %{ -+ __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), ++ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), + as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); + %} + @@ -39673,10 +37220,8 @@ index 00000000000..588887e1d96 + ins_cost(ALU_COST + BRANCH_COST); + + format %{ -+ "bneg$cop $op1, $op2, skip\t#@cmovI_cmpI\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpI\n\t" ++ %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, @@ -39684,7 +37229,7 @@ index 00000000000..588887e1d96 + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); +%} + +instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop) %{ @@ -39692,18 +37237,16 @@ index 00000000000..588887e1d96 + ins_cost(ALU_COST + BRANCH_COST); + + format %{ -+ "bneg$cop $op1, $op2, skip\t#@cmovI_cmpU\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpU\n\t" ++ %} + + ins_encode %{ -+ __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, ++ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); +%} + +instruct cmovI_cmpL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOp cop) %{ @@ -39711,10 +37254,8 @@ index 00000000000..588887e1d96 + ins_cost(ALU_COST + BRANCH_COST); + + format %{ -+ "bneg$cop $op1, $op2, skip\t#@cmovI_cmpL\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpL\n\t" ++ %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, @@ -39722,7 +37263,24 @@ index 00000000000..588887e1d96 + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); ++%} ++ ++instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) %{ ++ match(Set dst (CMoveI (Binary cop (CmpUL op1 op2)) (Binary dst src))); ++ ins_cost(ALU_COST + BRANCH_COST); ++ ++ format %{ ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovI_cmpUL\n\t" ++ %} ++ ++ ins_encode %{ ++ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, ++ as_Register($op1$$reg), as_Register($op2$$reg), ++ as_Register($dst$$reg), as_Register($src$$reg)); ++ %} ++ ++ ins_pipe(pipe_class_compare); +%} + +instruct cmovL_cmpL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOp cop) %{ @@ -39730,10 +37288,8 @@ index 00000000000..588887e1d96 + ins_cost(ALU_COST + BRANCH_COST); + + format %{ -+ "bneg$cop $op1, $op2, skip\t#@cmovL_cmpL\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpL\n\t" ++ %} + + ins_encode %{ + __ enc_cmove($cop$$cmpcode, @@ -39741,7 +37297,7 @@ index 00000000000..588887e1d96 + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); +%} + +instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop) %{ @@ -39749,38 +37305,51 @@ index 00000000000..588887e1d96 + ins_cost(ALU_COST + BRANCH_COST); + + format %{ -+ "bneg$cop $op1, $op2, skip\t#@cmovL_cmpUL\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpUL\n\t" ++ %} + + ins_encode %{ -+ __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, ++ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); +%} + -+instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) %{ -+ match(Set dst (CMoveI (Binary cop (CmpUL op1 op2)) (Binary dst src))); ++instruct cmovL_cmpI(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOp cop) %{ ++ match(Set dst (CMoveL (Binary cop (CmpI op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); ++ + format %{ -+ "bneg$cop $op1, $op2\t#@cmovI_cmpUL\n\t" -+ "mv $dst, $src\n\t" -+ "skip:" -+ %} ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpI\n\t" ++ %} + + ins_encode %{ -+ __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, ++ __ enc_cmove($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_Register($dst$$reg), as_Register($src$$reg)); + %} + -+ ins_pipe(pipe_slow); ++ ins_pipe(pipe_class_compare); +%} + ++instruct cmovL_cmpU(iRegLNoSp dst, iRegL src, iRegI op1, iRegI op2, cmpOpU cop) %{ ++ match(Set dst (CMoveL (Binary cop (CmpU op1 op2)) (Binary dst src))); ++ ins_cost(ALU_COST + BRANCH_COST); ++ ++ format %{ ++ "CMove $dst, ($op1 $cop $op2), $dst, $src\t#@cmovL_cmpU\n\t" ++ %} ++ ++ ins_encode %{ ++ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, ++ as_Register($op1$$reg), as_Register($op2$$reg), ++ as_Register($dst$$reg), as_Register($src$$reg)); ++ %} ++ ++ ins_pipe(pipe_class_compare); ++%} + +// ============================================================================ +// Procedure Call/Return Instructions @@ -39920,7 +37489,7 @@ index 00000000000..588887e1d96 +instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); ++ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + @@ -39938,7 +37507,7 @@ index 00000000000..588887e1d96 +instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); ++ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + @@ -39955,7 +37524,7 @@ index 00000000000..588887e1d96 +instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); ++ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + @@ -39973,7 +37542,7 @@ index 00000000000..588887e1d96 + iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, + rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); ++ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); + match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); + effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); + @@ -40119,7 +37688,6 @@ index 00000000000..588887e1d96 + iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) +%{ + match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -+ predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); + effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, + TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); + @@ -40133,28 +37701,9 @@ index 00000000000..588887e1d96 +%} + + -+instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -+ iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -+ iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) -+%{ -+ match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -+ predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); -+ effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, -+ TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); -+ -+ format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result" %} -+ ins_encode %{ -+ __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, -+ $result$$Register, $tmp1$$Register, $tmp2$$Register, -+ $tmp3$$Register, $tmp4$$Register, true /* isL */); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ +// clearing of an array +instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy) +%{ -+ predicate(!UseRVV); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL cnt, USE_KILL base); + @@ -40174,8 +37723,7 @@ index 00000000000..588887e1d96 + +instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr) +%{ -+ predicate(!UseRVV && (uint64_t)n->in(2)->get_long() -+ < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)); ++ predicate((uint64_t)n->in(2)->get_long() < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)); + match(Set dummy (ClearArray cnt base)); + effect(USE_KILL base, KILL cr); + @@ -40192,7 +37740,7 @@ index 00000000000..588887e1d96 +instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); ++ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + @@ -40208,7 +37756,7 @@ index 00000000000..588887e1d96 +instruct string_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, + iRegI_R10 result, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); ++ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (StrEquals (Binary str1 str2) cnt)); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + @@ -40225,7 +37773,7 @@ index 00000000000..588887e1d96 + iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, + iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); ++ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); + @@ -40242,7 +37790,7 @@ index 00000000000..588887e1d96 + iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, + iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) +%{ -+ predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); ++ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); + match(Set result (AryEq ary1 ary2)); + effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); + @@ -40455,10 +38003,10 @@ index 00000000000..588887e1d96 +// End: diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad new file mode 100644 -index 00000000000..4488c1c4031 +index 0000000000..7dda004cd3 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv_b.ad -@@ -0,0 +1,527 @@ +@@ -0,0 +1,466 @@ +// +// Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -40486,88 +38034,12 @@ index 00000000000..4488c1c4031 + +// RISCV Bit-Manipulation Extension Architecture Description File + -+instruct rorI_imm_rvb(iRegINoSp dst, iRegI src, immI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateRight src shift)); -+ -+ format %{ "roriw $dst, $src, ($shift & 0x1f)\t#@rorI_imm_rvb" %} -+ -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ roriw(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x1f); -+ %} -+ -+ ins_pipe(ialu_reg_shift); -+%} -+ -+instruct rorL_imm_rvb(iRegLNoSp dst, iRegL src, immI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateRight src shift)); -+ -+ format %{ "rori $dst, $src, ($shift & 0x3f)\t#@rorL_imm_rvb" %} -+ -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ rori(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x3f); -+ %} -+ -+ ins_pipe(ialu_reg_shift); -+%} -+ -+instruct rorI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateRight src shift)); -+ -+ format %{ "rorw $dst, $src, $shift\t#@rorI_reg_rvb" %} -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ rorw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -+ %} -+ ins_pipe(ialu_reg_reg); -+%} -+ -+instruct rorL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateRight src shift)); -+ -+ format %{ "ror $dst, $src, $shift\t#@rorL_reg_rvb" %} -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ ror(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -+ %} -+ ins_pipe(ialu_reg_reg); -+%} -+ -+instruct rolI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateLeft src shift)); -+ -+ format %{ "rolw $dst, $src, $shift\t#@rolI_reg_rvb" %} -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ rolw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -+ %} -+ ins_pipe(ialu_reg_reg); -+%} -+ -+instruct rolL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{ -+ predicate(UseRVB); -+ match(Set dst (RotateLeft src shift)); -+ -+ format %{ "rol $dst, $src, $shift\t#@rolL_reg_rvb" %} -+ ins_cost(ALU_COST); -+ ins_encode %{ -+ __ rol(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -+ %} -+ ins_pipe(ialu_reg_reg); -+%} -+ +// Convert oop into int for vectors alignment masking -+instruct convP2I_rvb(iRegINoSp dst, iRegP src) %{ -+ predicate(UseRVB); ++instruct convP2I_b(iRegINoSp dst, iRegP src) %{ ++ predicate(UseZba); + match(Set dst (ConvL2I (CastP2X src))); + -+ format %{ "zext.w $dst, $src\t# ptr -> int @convP2I_rvb" %} ++ format %{ "zext.w $dst, $src\t# ptr -> int @convP2I_b" %} + + ins_cost(ALU_COST); + ins_encode %{ @@ -40578,11 +38050,11 @@ index 00000000000..4488c1c4031 +%} + +// byte to int -+instruct convB2I_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_24 lshift, immI_24 rshift) %{ -+ predicate(UseRVB); ++instruct convB2I_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_24 lshift, immI_24 rshift) %{ ++ predicate(UseZbb); + match(Set dst (RShiftI (LShiftI src lshift) rshift)); + -+ format %{ "sext.b $dst, $src\t# b2i, #@convB2I_reg_reg_rvb" %} ++ format %{ "sext.b $dst, $src\t# b2i, #@convB2I_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ @@ -40593,11 +38065,11 @@ index 00000000000..4488c1c4031 +%} + +// int to short -+instruct convI2S_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_16 lshift, immI_16 rshift) %{ -+ predicate(UseRVB); ++instruct convI2S_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_16 lshift, immI_16 rshift) %{ ++ predicate(UseZbb); + match(Set dst (RShiftI (LShiftI src lshift) rshift)); + -+ format %{ "sext.h $dst, $src\t# i2s, #@convI2S_reg_reg_rvb" %} ++ format %{ "sext.h $dst, $src\t# i2s, #@convI2S_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ @@ -40608,11 +38080,11 @@ index 00000000000..4488c1c4031 +%} + +// short to unsigned int -+instruct convS2UI_reg_reg_rvb(iRegINoSp dst, iRegIorL2I src, immI_16bits mask) %{ -+ predicate(UseRVB); ++instruct convS2UI_reg_reg_b(iRegINoSp dst, iRegIorL2I src, immI_16bits mask) %{ ++ predicate(UseZbb); + match(Set dst (AndI src mask)); + -+ format %{ "zext.h $dst, $src\t# s2ui, #@convS2UI_reg_reg_rvb" %} ++ format %{ "zext.h $dst, $src\t# s2ui, #@convS2UI_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ @@ -40623,11 +38095,11 @@ index 00000000000..4488c1c4031 +%} + +// int to unsigned long (zero extend) -+instruct convI2UL_reg_reg_rvb(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ -+ predicate(UseRVB); ++instruct convI2UL_reg_reg_b(iRegLNoSp dst, iRegIorL2I src, immL_32bits mask) %{ ++ predicate(UseZba); + match(Set dst (AndL (ConvI2L src) mask)); + -+ format %{ "zext.w $dst, $src\t# i2ul, #@convI2UL_reg_reg_rvb" %} ++ format %{ "zext.w $dst, $src\t# i2ul, #@convI2UL_reg_reg_b" %} + + ins_cost(ALU_COST); + ins_encode %{ @@ -40638,12 +38110,12 @@ index 00000000000..4488c1c4031 +%} + +// BSWAP instructions -+instruct bytes_reverse_int_rvb(iRegINoSp dst, iRegIorL2I src) %{ -+ predicate(UseRVB); ++instruct bytes_reverse_int_b(iRegINoSp dst, iRegIorL2I src) %{ ++ predicate(UseZbb); + match(Set dst (ReverseBytesI src)); + + ins_cost(ALU_COST * 2); -+ format %{ "revb_w_w $dst, $src\t#@bytes_reverse_int_rvb" %} ++ format %{ "revb_w_w $dst, $src\t#@bytes_reverse_int_b" %} + + ins_encode %{ + __ revb_w_w(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40652,12 +38124,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct bytes_reverse_long_rvb(iRegLNoSp dst, iRegL src) %{ -+ predicate(UseRVB); ++instruct bytes_reverse_long_b(iRegLNoSp dst, iRegL src) %{ ++ predicate(UseZbb); + match(Set dst (ReverseBytesL src)); + + ins_cost(ALU_COST); -+ format %{ "rev8 $dst, $src\t#@bytes_reverse_long_rvb" %} ++ format %{ "rev8 $dst, $src\t#@bytes_reverse_long_b" %} + + ins_encode %{ + __ rev8(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40666,12 +38138,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct bytes_reverse_unsigned_short_rvb(iRegINoSp dst, iRegIorL2I src) %{ -+ predicate(UseRVB); ++instruct bytes_reverse_unsigned_short_b(iRegINoSp dst, iRegIorL2I src) %{ ++ predicate(UseZbb); + match(Set dst (ReverseBytesUS src)); + + ins_cost(ALU_COST * 2); -+ format %{ "revb_h_h_u $dst, $src\t#@bytes_reverse_unsigned_short_rvb" %} ++ format %{ "revb_h_h_u $dst, $src\t#@bytes_reverse_unsigned_short_b" %} + + ins_encode %{ + __ revb_h_h_u(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40680,12 +38152,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct bytes_reverse_short_rvb(iRegINoSp dst, iRegIorL2I src) %{ -+ predicate(UseRVB); ++instruct bytes_reverse_short_b(iRegINoSp dst, iRegIorL2I src) %{ ++ predicate(UseZbb); + match(Set dst (ReverseBytesS src)); + + ins_cost(ALU_COST * 2); -+ format %{ "revb_h_h $dst, $src\t#@bytes_reverse_short_rvb" %} ++ format %{ "revb_h_h $dst, $src\t#@bytes_reverse_short_b" %} + + ins_encode %{ + __ revb_h_h(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40695,12 +38167,12 @@ index 00000000000..4488c1c4031 +%} + +// Shift Add Pointer -+instruct shaddP_reg_reg_rvb(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale imm) %{ -+ predicate(UseRVB); ++instruct shaddP_reg_reg_b(iRegPNoSp dst, iRegP src1, iRegL src2, immIScale imm) %{ ++ predicate(UseZba); + match(Set dst (AddP src1 (LShiftL src2 imm))); + + ins_cost(ALU_COST); -+ format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_rvb" %} ++ format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), @@ -40713,12 +38185,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct shaddP_reg_reg_ext_rvb(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale imm) %{ -+ predicate(UseRVB); ++instruct shaddP_reg_reg_ext_b(iRegPNoSp dst, iRegP src1, iRegI src2, immIScale imm) %{ ++ predicate(UseZba); + match(Set dst (AddP src1 (LShiftL (ConvI2L src2) imm))); + + ins_cost(ALU_COST); -+ format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_ext_rvb" %} ++ format %{ "shadd $dst, $src2, $src1, $imm\t# ptr, #@shaddP_reg_reg_ext_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), @@ -40732,12 +38204,12 @@ index 00000000000..4488c1c4031 +%} + +// Shift Add Long -+instruct shaddL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immIScale imm) %{ -+ predicate(UseRVB); ++instruct shaddL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immIScale imm) %{ ++ predicate(UseZba); + match(Set dst (AddL src1 (LShiftL src2 imm))); + + ins_cost(ALU_COST); -+ format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_rvb" %} ++ format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), @@ -40750,12 +38222,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct shaddL_reg_reg_ext_rvb(iRegLNoSp dst, iRegL src1, iRegI src2, immIScale imm) %{ -+ predicate(UseRVB); ++instruct shaddL_reg_reg_ext_b(iRegLNoSp dst, iRegL src1, iRegI src2, immIScale imm) %{ ++ predicate(UseZba); + match(Set dst (AddL src1 (LShiftL (ConvI2L src2) imm))); + + ins_cost(ALU_COST); -+ format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_ext_rvb" %} ++ format %{ "shadd $dst, $src2, $src1, $imm\t#@shaddL_reg_reg_ext_b" %} + + ins_encode %{ + __ shadd(as_Register($dst$$reg), @@ -40769,12 +38241,12 @@ index 00000000000..4488c1c4031 +%} + +// Zeros Count instructions -+instruct countLeadingZerosI_rvb(iRegINoSp dst, iRegIorL2I src) %{ -+ predicate(UseRVB); ++instruct countLeadingZerosI_b(iRegINoSp dst, iRegIorL2I src) %{ ++ predicate(UseZbb); + match(Set dst (CountLeadingZerosI src)); + + ins_cost(ALU_COST); -+ format %{ "clzw $dst, $src\t#@countLeadingZerosI_rvb" %} ++ format %{ "clzw $dst, $src\t#@countLeadingZerosI_b" %} + + ins_encode %{ + __ clzw(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40783,12 +38255,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct countLeadingZerosL_rvb(iRegINoSp dst, iRegL src) %{ -+ predicate(UseRVB); ++instruct countLeadingZerosL_b(iRegINoSp dst, iRegL src) %{ ++ predicate(UseZbb); + match(Set dst (CountLeadingZerosL src)); + + ins_cost(ALU_COST); -+ format %{ "clz $dst, $src\t#@countLeadingZerosL_rvb" %} ++ format %{ "clz $dst, $src\t#@countLeadingZerosL_b" %} + + ins_encode %{ + __ clz(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40797,12 +38269,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct countTrailingZerosI_rvb(iRegINoSp dst, iRegIorL2I src) %{ -+ predicate(UseRVB); ++instruct countTrailingZerosI_b(iRegINoSp dst, iRegIorL2I src) %{ ++ predicate(UseZbb); + match(Set dst (CountTrailingZerosI src)); + + ins_cost(ALU_COST); -+ format %{ "ctzw $dst, $src\t#@countTrailingZerosI_rvb" %} ++ format %{ "ctzw $dst, $src\t#@countTrailingZerosI_b" %} + + ins_encode %{ + __ ctzw(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40811,12 +38283,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg); +%} + -+instruct countTrailingZerosL_rvb(iRegINoSp dst, iRegL src) %{ -+ predicate(UseRVB); ++instruct countTrailingZerosL_b(iRegINoSp dst, iRegL src) %{ ++ predicate(UseZbb); + match(Set dst (CountTrailingZerosL src)); + + ins_cost(ALU_COST); -+ format %{ "ctz $dst, $src\t#@countTrailingZerosL_rvb" %} ++ format %{ "ctz $dst, $src\t#@countTrailingZerosL_b" %} + + ins_encode %{ + __ ctz(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40826,12 +38298,12 @@ index 00000000000..4488c1c4031 +%} + +// Population Count instructions -+instruct popCountI_rvb(iRegINoSp dst, iRegIorL2I src) %{ ++instruct popCountI_b(iRegINoSp dst, iRegIorL2I src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountI src)); + + ins_cost(ALU_COST); -+ format %{ "cpopw $dst, $src\t#@popCountI_rvb" %} ++ format %{ "cpopw $dst, $src\t#@popCountI_b" %} + + ins_encode %{ + __ cpopw(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40841,12 +38313,12 @@ index 00000000000..4488c1c4031 +%} + +// Note: Long/bitCount(long) returns an int. -+instruct popCountL_rvb(iRegINoSp dst, iRegL src) %{ ++instruct popCountL_b(iRegINoSp dst, iRegL src) %{ + predicate(UsePopCountInstruction); + match(Set dst (PopCountL src)); + + ins_cost(ALU_COST); -+ format %{ "cpop $dst, $src\t#@popCountL_rvb" %} ++ format %{ "cpop $dst, $src\t#@popCountL_b" %} + + ins_encode %{ + __ cpop(as_Register($dst$$reg), as_Register($src$$reg)); @@ -40856,12 +38328,12 @@ index 00000000000..4488c1c4031 +%} + +// Max and Min -+instruct minI_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2) %{ -+ predicate(UseRVB); ++instruct minI_reg_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ ++ predicate(UseZbb); + match(Set dst (MinI src1 src2)); + + ins_cost(ALU_COST); -+ format %{ "min $dst, $src1, $src2\t#@minI_reg_rvb" %} ++ format %{ "min $dst, $src1, $src2\t#@minI_reg_b" %} + + ins_encode %{ + __ min(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg)); @@ -40870,12 +38342,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct maxI_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2) %{ -+ predicate(UseRVB); ++instruct maxI_reg_b(iRegINoSp dst, iRegI src1, iRegI src2) %{ ++ predicate(UseZbb); + match(Set dst (MaxI src1 src2)); + + ins_cost(ALU_COST); -+ format %{ "max $dst, $src1, $src2\t#@maxI_reg_rvb" %} ++ format %{ "max $dst, $src1, $src2\t#@maxI_reg_b" %} + + ins_encode %{ + __ max(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg)); @@ -40885,14 +38357,14 @@ index 00000000000..4488c1c4031 +%} + +// Abs -+instruct absI_reg_rvb(iRegINoSp dst, iRegI src) %{ -+ predicate(UseRVB); ++instruct absI_reg_b(iRegINoSp dst, iRegI src) %{ ++ predicate(UseZbb); + match(Set dst (AbsI src)); + + ins_cost(ALU_COST * 2); + format %{ + "negw t0, $src\n\t" -+ "max $dst, $src, t0\t#@absI_reg_rvb" ++ "max $dst, $src, t0\t#@absI_reg_b" + %} + + ins_encode %{ @@ -40903,14 +38375,14 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct absL_reg_rvb(iRegLNoSp dst, iRegL src) %{ -+ predicate(UseRVB); ++instruct absL_reg_b(iRegLNoSp dst, iRegL src) %{ ++ predicate(UseZbb); + match(Set dst (AbsL src)); + + ins_cost(ALU_COST * 2); + format %{ + "neg t0, $src\n\t" -+ "max $dst, $src, t0\t#@absL_reg_rvb" ++ "max $dst, $src, t0\t#@absL_reg_b" + %} + + ins_encode %{ @@ -40922,12 +38394,12 @@ index 00000000000..4488c1c4031 +%} + +// And Not -+instruct andnI_reg_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ -+ predicate(UseRVB); ++instruct andnI_reg_reg_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ ++ predicate(UseZbb); + match(Set dst (AndI src1 (XorI src2 m1))); + + ins_cost(ALU_COST); -+ format %{ "andn $dst, $src1, $src2\t#@andnI_reg_reg_rvb" %} ++ format %{ "andn $dst, $src1, $src2\t#@andnI_reg_reg_b" %} + + ins_encode %{ + __ andn(as_Register($dst$$reg), @@ -40938,12 +38410,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct andnL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ -+ predicate(UseRVB); ++instruct andnL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ ++ predicate(UseZbb); + match(Set dst (AndL src1 (XorL src2 m1))); + + ins_cost(ALU_COST); -+ format %{ "andn $dst, $src1, $src2\t#@andnL_reg_reg_rvb" %} ++ format %{ "andn $dst, $src1, $src2\t#@andnL_reg_reg_b" %} + + ins_encode %{ + __ andn(as_Register($dst$$reg), @@ -40955,12 +38427,12 @@ index 00000000000..4488c1c4031 +%} + +// Or Not -+instruct ornI_reg_reg_rvb(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ -+ predicate(UseRVB); ++instruct ornI_reg_reg_b(iRegINoSp dst, iRegI src1, iRegI src2, immI_M1 m1) %{ ++ predicate(UseZbb); + match(Set dst (OrI src1 (XorI src2 m1))); + + ins_cost(ALU_COST); -+ format %{ "orn $dst, $src1, $src2\t#@ornI_reg_reg_rvb" %} ++ format %{ "orn $dst, $src1, $src2\t#@ornI_reg_reg_b" %} + + ins_encode %{ + __ orn(as_Register($dst$$reg), @@ -40971,12 +38443,12 @@ index 00000000000..4488c1c4031 + ins_pipe(ialu_reg_reg); +%} + -+instruct ornL_reg_reg_rvb(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ -+ predicate(UseRVB); ++instruct ornL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ ++ predicate(UseZbb); + match(Set dst (OrL src1 (XorL src2 m1))); + + ins_cost(ALU_COST); -+ format %{ "orn $dst, $src1, $src2\t#@ornL_reg_reg_rvb" %} ++ format %{ "orn $dst, $src1, $src2\t#@ornL_reg_reg_b" %} + + ins_encode %{ + __ orn(as_Register($dst$$reg), @@ -40985,2085 +38457,29 @@ index 00000000000..4488c1c4031 + %} + + ins_pipe(ialu_reg_reg); ++ ++%} ++ ++// AndI 0b0..010..0 + ConvI2B ++instruct convI2Bool_andI_reg_immIpowerOf2(iRegINoSp dst, iRegIorL2I src, immIpowerOf2 mask) %{ ++ predicate(UseZbs); ++ match(Set dst (Conv2B (AndI src mask))); ++ ins_cost(ALU_COST); ++ ++ format %{ "bexti $dst, $src, $mask\t#@convI2Bool_andI_reg_immIpowerOf2" %} ++ ins_encode %{ ++ __ bexti($dst$$Register, $src$$Register, exact_log2((juint)($mask$$constant))); ++ %} ++ ++ ins_pipe(ialu_reg_reg); +%} \ No newline at end of file -diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad -new file mode 100644 -index 00000000000..3828e096b21 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/riscv_v.ad -@@ -0,0 +1,2065 @@ -+// -+// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+// Copyright (c) 2020, Arm Limited. All rights reserved. -+// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+// -+// 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. -+// -+// -+ -+// RISCV Vector Extension Architecture Description File -+ -+opclass vmemA(indirect); -+ -+source_hpp %{ -+ bool op_vec_supported(int opcode); -+%} -+ -+source %{ -+ -+ static void loadStore(C2_MacroAssembler masm, bool is_store, -+ VectorRegister reg, BasicType bt, Register base) { -+ Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -+ masm.vsetvli(t0, x0, sew); -+ if (is_store) { -+ masm.vsex_v(reg, base, sew); -+ } else { -+ masm.vlex_v(reg, base, sew); -+ } -+ } -+ -+ bool op_vec_supported(int opcode) { -+ switch (opcode) { -+ // No multiply reduction instructions -+ case Op_MulReductionVD: -+ case Op_MulReductionVF: -+ case Op_MulReductionVI: -+ case Op_MulReductionVL: -+ // Others -+ case Op_Extract: -+ case Op_ExtractB: -+ case Op_ExtractC: -+ case Op_ExtractD: -+ case Op_ExtractF: -+ case Op_ExtractI: -+ case Op_ExtractL: -+ case Op_ExtractS: -+ case Op_ExtractUB: -+ // Vector API specific -+ case Op_AndReductionV: -+ case Op_OrReductionV: -+ case Op_XorReductionV: -+ case Op_LoadVectorGather: -+ case Op_StoreVectorScatter: -+ case Op_VectorBlend: -+ case Op_VectorCast: -+ case Op_VectorCastB2X: -+ case Op_VectorCastD2X: -+ case Op_VectorCastF2X: -+ case Op_VectorCastI2X: -+ case Op_VectorCastL2X: -+ case Op_VectorCastS2X: -+ case Op_VectorInsert: -+ case Op_VectorLoadConst: -+ case Op_VectorLoadMask: -+ case Op_VectorLoadShuffle: -+ case Op_VectorMaskCmp: -+ case Op_VectorRearrange: -+ case Op_VectorReinterpret: -+ case Op_VectorStoreMask: -+ case Op_VectorTest: -+ return false; -+ default: -+ return UseRVV; -+ } -+ } -+ -+%} -+ -+definitions %{ -+ int_def VEC_COST (200, 200); -+%} -+ -+// All VEC instructions -+ -+// vector load/store -+instruct loadV(vReg dst, vmemA mem) %{ -+ match(Set dst (LoadVector mem)); -+ ins_cost(VEC_COST); -+ format %{ "vle $dst, $mem\t#@loadV" %} -+ ins_encode %{ -+ VectorRegister dst_reg = as_VectorRegister($dst$$reg); -+ loadStore(C2_MacroAssembler(&cbuf), false, dst_reg, -+ Matcher::vector_element_basic_type(this), as_Register($mem$$base)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct storeV(vReg src, vmemA mem) %{ -+ match(Set mem (StoreVector mem src)); -+ ins_cost(VEC_COST); -+ format %{ "vse $src, $mem\t#@storeV" %} -+ ins_encode %{ -+ VectorRegister src_reg = as_VectorRegister($src$$reg); -+ loadStore(C2_MacroAssembler(&cbuf), true, src_reg, -+ Matcher::vector_element_basic_type(this, $src), as_Register($mem$$base)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector abs -+ -+instruct vabsB(vReg dst, vReg src, vReg tmp) %{ -+ match(Set dst (AbsVB src)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vrsub.vi $tmp, 0, $src\t#@vabsB\n\t" -+ "vmax.vv $dst, $tmp, $src" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -+ __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vabsS(vReg dst, vReg src, vReg tmp) %{ -+ match(Set dst (AbsVS src)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vrsub.vi $tmp, 0, $src\t#@vabsS\n\t" -+ "vmax.vv $dst, $tmp, $src" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -+ __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vabsI(vReg dst, vReg src, vReg tmp) %{ -+ match(Set dst (AbsVI src)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vrsub.vi $tmp, 0, $src\t#@vabsI\n\t" -+ "vmax.vv $dst, $tmp, $src" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -+ __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vabsL(vReg dst, vReg src, vReg tmp) %{ -+ match(Set dst (AbsVL src)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vrsub.vi $tmp, 0, $src\t#@vabsL\n\t" -+ "vmax.vv $dst, $tmp, $src" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -+ __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vabsF(vReg dst, vReg src) %{ -+ match(Set dst (AbsVF src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vabsD(vReg dst, vReg src) %{ -+ match(Set dst (AbsVD src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector add -+ -+instruct vaddB(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVB src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vadd.vv $dst, $src1, $src2\t#@vaddB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vaddS(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVS src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vadd.vv $dst, $src1, $src2\t#@vaddS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vaddI(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVI src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vadd.vv $dst, $src1, $src2\t#@vaddI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vaddL(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVL src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vadd.vv $dst, $src1, $src2\t#@vaddL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vaddF(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVF src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vaddD(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AddVD src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfadd_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector and -+ -+instruct vand(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (AndV src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vand.vv $dst, $src1, $src2\t#@vand" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vand_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector or -+ -+instruct vor(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (OrV src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vor.vv $dst, $src1, $src2\t#@vor" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vor_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector xor -+ -+instruct vxor(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (XorV src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vxor.vv $dst, $src1, $src2\t#@vxor" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vxor_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector float div -+ -+instruct vdivF(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (DivVF src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfdiv_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vdivD(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (DivVD src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfdiv_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector integer max/min -+ -+instruct vmax(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && -+ n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); -+ match(Set dst (MaxV src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmax.vv $dst, $src1, $src2\t#@vmax" %} -+ ins_encode %{ -+ BasicType bt = Matcher::vector_element_basic_type(this); -+ Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -+ __ vsetvli(t0, x0, sew); -+ __ vmax_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmin(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && -+ n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); -+ match(Set dst (MinV src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmin.vv $dst, $src1, $src2\t#@vmin" %} -+ ins_encode %{ -+ BasicType bt = Matcher::vector_element_basic_type(this); -+ Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -+ __ vsetvli(t0, x0, sew); -+ __ vmin_vv(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector float-point max/min -+ -+instruct vmaxF(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -+ match(Set dst (MaxV src1 src2)); -+ effect(TEMP_DEF dst); -+ ins_cost(VEC_COST); -+ format %{ "vmaxF $dst, $src1, $src2\t#@vmaxF" %} -+ ins_encode %{ -+ __ minmax_FD_v(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -+ false /* is_double */, false /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmaxD(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -+ match(Set dst (MaxV src1 src2)); -+ effect(TEMP_DEF dst); -+ ins_cost(VEC_COST); -+ format %{ "vmaxD $dst, $src1, $src2\t#@vmaxD" %} -+ ins_encode %{ -+ __ minmax_FD_v(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -+ true /* is_double */, false /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vminF(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -+ match(Set dst (MinV src1 src2)); -+ effect(TEMP_DEF dst); -+ ins_cost(VEC_COST); -+ format %{ "vminF $dst, $src1, $src2\t#@vminF" %} -+ ins_encode %{ -+ __ minmax_FD_v(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -+ false /* is_double */, true /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vminD(vReg dst, vReg src1, vReg src2) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -+ match(Set dst (MinV src1 src2)); -+ effect(TEMP_DEF dst); -+ ins_cost(VEC_COST); -+ format %{ "vminD $dst, $src1, $src2\t#@vminD" %} -+ ins_encode %{ -+ __ minmax_FD_v(as_VectorRegister($dst$$reg), -+ as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -+ true /* is_double */, true /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector fmla -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vfmlaF(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vfmlaD(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector fmls -+ -+// dst_src1 = dst_src1 + -src2 * src3 -+// dst_src1 = dst_src1 + src2 * -src3 -+instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3))); -+ match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3)))); -+ ins_cost(VEC_COST); -+ format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 + -src2 * src3 -+// dst_src1 = dst_src1 + src2 * -src3 -+instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3))); -+ match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3)))); -+ ins_cost(VEC_COST); -+ format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector fnmla -+ -+// dst_src1 = -dst_src1 + -src2 * src3 -+// dst_src1 = -dst_src1 + src2 * -src3 -+instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3))); -+ match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3)))); -+ ins_cost(VEC_COST); -+ format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = -dst_src1 + -src2 * src3 -+// dst_src1 = -dst_src1 + src2 * -src3 -+instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3))); -+ match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3)))); -+ ins_cost(VEC_COST); -+ format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector fnmls -+ -+// dst_src1 = -dst_src1 + src2 * src3 -+instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = -dst_src1 + src2 * src3 -+instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{ -+ predicate(UseFMA); -+ match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector mla -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vmlaB(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (AddVB dst_src1 (MulVB src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vmlaS(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (AddVS dst_src1 (MulVS src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vmlaI(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (AddVI dst_src1 (MulVI src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 + src2 * src3 -+instruct vmlaL(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (AddVL dst_src1 (MulVL src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector mls -+ -+// dst_src1 = dst_src1 - src2 * src3 -+instruct vmlsB(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (SubVB dst_src1 (MulVB src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 - src2 * src3 -+instruct vmlsS(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (SubVS dst_src1 (MulVS src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 - src2 * src3 -+instruct vmlsI(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (SubVI dst_src1 (MulVI src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// dst_src1 = dst_src1 - src2 * src3 -+instruct vmlsL(vReg dst_src1, vReg src2, vReg src3) %{ -+ match(Set dst_src1 (SubVL dst_src1 (MulVL src2 src3))); -+ ins_cost(VEC_COST); -+ format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -+ as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector mul -+ -+instruct vmulB(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVB src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmul.vv $dst, $src1, $src2\t#@vmulB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmulS(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVS src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmul.vv $dst, $src1, $src2\t#@vmulS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmulI(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVI src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmul.vv $dst, $src1, $src2\t#@vmulI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmulL(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVL src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vmul.vv $dst, $src1, $src2\t#@vmulL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmulF(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVF src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vmulD(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (MulVD src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector fneg -+ -+instruct vnegF(vReg dst, vReg src) %{ -+ match(Set dst (NegVF src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vnegD(vReg dst, vReg src) %{ -+ match(Set dst (NegVD src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// popcount vector -+ -+instruct vpopcountI(iRegINoSp dst, vReg src) %{ -+ match(Set dst (PopCountVI src)); -+ format %{ "vpopc.m $dst, $src\t#@vpopcountI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vpopc_m(as_Register($dst$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector add reduction -+ -+instruct reduce_addB(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -+ match(Set dst (AddReductionVI src1 src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vmv.s.x $tmp, $src1\t#@reduce_addB\n\t" -+ "vredsum.vs $tmp, $src2, $tmp\n\t" -+ "vmv.x.s $dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct reduce_addS(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -+ match(Set dst (AddReductionVI src1 src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vmv.s.x $tmp, $src1\t#@reduce_addS\n\t" -+ "vredsum.vs $tmp, $src2, $tmp\n\t" -+ "vmv.x.s $dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -+ match(Set dst (AddReductionVI src1 src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vmv.s.x $tmp, $src1\t#@reduce_addI\n\t" -+ "vredsum.vs $tmp, $src2, $tmp\n\t" -+ "vmv.x.s $dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct reduce_addL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -+ match(Set dst (AddReductionVL src1 src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vmv.s.x $tmp, $src1\t#@reduce_addL\n\t" -+ "vredsum.vs $tmp, $src2, $tmp\n\t" -+ "vmv.x.s $dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct reduce_addF(fRegF src1_dst, vReg src2, vReg tmp) %{ -+ match(Set src1_dst (AddReductionVF src1_dst src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addF\n\t" -+ "vfredosum.vs $tmp, $src2, $tmp\n\t" -+ "vfmv.f.s $src1_dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); -+ __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct reduce_addD(fRegD src1_dst, vReg src2, vReg tmp) %{ -+ match(Set src1_dst (AddReductionVD src1_dst src2)); -+ effect(TEMP tmp); -+ ins_cost(VEC_COST); -+ format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addD\n\t" -+ "vfredosum.vs $tmp, $src2, $tmp\n\t" -+ "vfmv.f.s $src1_dst, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); -+ __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp$$reg)); -+ __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector integer max reduction -+instruct vreduce_maxB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_maxB $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ Label Ldone; -+ __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -+ __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -+ __ bind(Ldone); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_maxS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_maxS $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ Label Ldone; -+ __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -+ __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -+ __ bind(Ldone); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_maxI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_maxI $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_maxL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_maxL $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector integer min reduction -+instruct vreduce_minB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_minB $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ Label Ldone; -+ __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -+ __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -+ __ bind(Ldone); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_minS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_minS $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ Label Ldone; -+ __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -+ __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -+ __ bind(Ldone); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_minI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_minI $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_minL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP tmp); -+ format %{ "vreduce_minL $dst, $src1, $src2, $tmp" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -+ __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -+ __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector float max reduction -+ -+instruct vreduce_maxF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -+ format %{ "reduce_maxF $dst, $src1, $src2, $tmp1, $tmp2" %} -+ ins_encode %{ -+ __ reduce_minmax_FD_v($dst$$FloatRegister, -+ $src1$$FloatRegister, as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -+ false /* is_double */, false /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_maxD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -+ match(Set dst (MaxReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -+ format %{ "reduce_maxD $dst, $src1, $src2, $tmp1, $tmp2" %} -+ ins_encode %{ -+ __ reduce_minmax_FD_v($dst$$FloatRegister, -+ $src1$$FloatRegister, as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -+ true /* is_double */, false /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector float min reduction -+ -+instruct vreduce_minF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -+ format %{ "reduce_minF $dst, $src1, $src2, $tmp1, $tmp2" %} -+ ins_encode %{ -+ __ reduce_minmax_FD_v($dst$$FloatRegister, -+ $src1$$FloatRegister, as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -+ false /* is_double */, true /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vreduce_minD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ -+ predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -+ match(Set dst (MinReductionV src1 src2)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -+ format %{ "reduce_minD $dst, $src1, $src2, $tmp1, $tmp2" %} -+ ins_encode %{ -+ __ reduce_minmax_FD_v($dst$$FloatRegister, -+ $src1$$FloatRegister, as_VectorRegister($src2$$reg), -+ as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -+ true /* is_double */, true /* is_min */); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector Math.rint, floor, ceil -+ -+instruct vroundD(vReg dst, vReg src, immI rmode) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -+ match(Set dst (RoundDoubleModeV src rmode)); -+ format %{ "vroundD $dst, $src, $rmode" %} -+ ins_encode %{ -+ switch ($rmode$$constant) { -+ case RoundDoubleModeNode::rmode_rint: -+ __ csrwi(CSR_FRM, C2_MacroAssembler::rne); -+ __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ break; -+ case RoundDoubleModeNode::rmode_floor: -+ __ csrwi(CSR_FRM, C2_MacroAssembler::rdn); -+ __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ break; -+ case RoundDoubleModeNode::rmode_ceil: -+ __ csrwi(CSR_FRM, C2_MacroAssembler::rup); -+ __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ break; -+ default: -+ ShouldNotReachHere(); -+ break; -+ } -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector replicate -+ -+instruct replicateB(vReg dst, iRegIorL2I src) %{ -+ match(Set dst (ReplicateB src)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.x $dst, $src\t#@replicateB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateS(vReg dst, iRegIorL2I src) %{ -+ match(Set dst (ReplicateS src)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.x $dst, $src\t#@replicateS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateI(vReg dst, iRegIorL2I src) %{ -+ match(Set dst (ReplicateI src)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.x $dst, $src\t#@replicateI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateL(vReg dst, iRegL src) %{ -+ match(Set dst (ReplicateL src)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.x $dst, $src\t#@replicateL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateB_imm5(vReg dst, immI5 con) %{ -+ match(Set dst (ReplicateB con)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.i $dst, $con\t#@replicateB_imm5" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateS_imm5(vReg dst, immI5 con) %{ -+ match(Set dst (ReplicateS con)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.i $dst, $con\t#@replicateS_imm5" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateI_imm5(vReg dst, immI5 con) %{ -+ match(Set dst (ReplicateI con)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.i $dst, $con\t#@replicateI_imm5" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateL_imm5(vReg dst, immL5 con) %{ -+ match(Set dst (ReplicateL con)); -+ ins_cost(VEC_COST); -+ format %{ "vmv.v.i $dst, $con\t#@replicateL_imm5" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateF(vReg dst, fRegF src) %{ -+ match(Set dst (ReplicateF src)); -+ ins_cost(VEC_COST); -+ format %{ "vfmv.v.f $dst, $src\t#@replicateF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct replicateD(vReg dst, fRegD src) %{ -+ match(Set dst (ReplicateD src)); -+ ins_cost(VEC_COST); -+ format %{ "vfmv.v.f $dst, $src\t#@replicateD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector shift -+ -+instruct vasrB(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (RShiftVB src shift)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift 7\t#@vasrB\n\t" -+ "vsra.vi $dst, $src, 7, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0\n\t" -+ "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ // if shift > BitsPerByte - 1, clear the low BitsPerByte - 1 bits -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ BitsPerByte - 1, Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrS(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (RShiftVS src shift)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift, 15\t#@vasrS\n\t" -+ "vsra.vi $dst, $src, 15, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0\n\t" -+ "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ // if shift > BitsPerShort - 1, clear the low BitsPerShort - 1 bits -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ BitsPerShort - 1, Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrI(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (RShiftVI src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsra.vv $dst, $src, $shift\t#@vasrI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrL(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (RShiftVL src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsra.vv $dst, $src, $shift\t#@vasrL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslB(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (LShiftVB src shift)); -+ ins_cost(VEC_COST); -+ effect( TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift, 7\t#@vlslB\n\t" -+ "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0\n\t" -+ "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ // if shift > BitsPerByte - 1, clear the element -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg), Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslS(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (LShiftVS src shift)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift, 15\t#@vlslS\n\t" -+ "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0\n\t" -+ "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ // if shift > BitsPerShort - 1, clear the element -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg), Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslI(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (LShiftVI src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vv $dst, $src, $shift\t#@vlslI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslL(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (LShiftVL src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vv $dst, $src, $shift\t# vector (D)" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrB(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (URShiftVB src shift)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift, 7\t#@vlsrB\n\t" -+ "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0, v0\n\t" -+ "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ // if shift > BitsPerByte - 1, clear the element -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg), Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrS(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (URShiftVS src shift)); -+ ins_cost(VEC_COST); -+ effect(TEMP_DEF dst); -+ format %{ "vmsgtu.vi v0, $shift, 15\t#@vlsrS\n\t" -+ "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -+ "vmnot.m v0, v0\n\t" -+ "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ // if shift > BitsPerShort - 1, clear the element -+ __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg), Assembler::v0_t); -+ // otherwise, shift -+ __ vmnot_m(v0, v0); -+ __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg), Assembler::v0_t); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+ -+instruct vlsrI(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (URShiftVI src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+ -+instruct vlsrL(vReg dst, vReg src, vReg shift) %{ -+ match(Set dst (URShiftVL src shift)); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($shift$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrB_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (RShiftVB src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsra.vi $dst, $src, $shift\t#@vasrB_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e8); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ if (con >= BitsPerByte) con = BitsPerByte - 1; -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrS_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (RShiftVS src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsra.vi $dst, $src, $shift\t#@vasrS_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e16); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ if (con >= BitsPerShort) con = BitsPerShort - 1; -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrI_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (RShiftVI src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vasrI_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e32); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vasrL_imm(vReg dst, vReg src, immI shift) %{ -+ predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -+ match(Set dst (RShiftVL src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vasrL_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e64); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (URShiftVB src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrB_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e8); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ if (con >= BitsPerByte) { -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (URShiftVS src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrS_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e16); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ if (con >= BitsPerShort) { -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (URShiftVI src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrI_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e32); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{ -+ predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -+ match(Set dst (URShiftVL src (RShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrL_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e64); -+ if (con == 0) { -+ __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslB_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (LShiftVB src (LShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vi $dst, $src, $shift\t#@vlslB_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e8); -+ if (con >= BitsPerByte) { -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslS_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (LShiftVS src (LShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vi $dst, $src, $shift\t#@vlslS_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e16); -+ if (con >= BitsPerShort) { -+ __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -+ as_VectorRegister($src$$reg)); -+ return; -+ } -+ __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslI_imm(vReg dst, vReg src, immI shift) %{ -+ match(Set dst (LShiftVI src (LShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vi $dst, $src, $shift\t#@vlslI_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vlslL_imm(vReg dst, vReg src, immI shift) %{ -+ predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -+ match(Set dst (LShiftVL src (LShiftCntV shift))); -+ ins_cost(VEC_COST); -+ format %{ "vsll.vi $dst, $src, $shift\t#@vlslL_imm" %} -+ ins_encode %{ -+ uint32_t con = (unsigned)$shift$$constant & 0x1f; -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vshiftcntB(vReg dst, iRegIorL2I cnt) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -+ match(Set dst (LShiftCntV cnt)); -+ match(Set dst (RShiftCntV cnt)); -+ format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vshiftcntS(vReg dst, iRegIorL2I cnt) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_SHORT || -+ n->bottom_type()->is_vect()->element_basic_type() == T_CHAR); -+ match(Set dst (LShiftCntV cnt)); -+ match(Set dst (RShiftCntV cnt)); -+ format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vshiftcntI(vReg dst, iRegIorL2I cnt) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_INT); -+ match(Set dst (LShiftCntV cnt)); -+ match(Set dst (RShiftCntV cnt)); -+ format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vshiftcntL(vReg dst, iRegIorL2I cnt) %{ -+ predicate(n->bottom_type()->is_vect()->element_basic_type() == T_LONG); -+ match(Set dst (LShiftCntV cnt)); -+ match(Set dst (RShiftCntV cnt)); -+ format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector sqrt -+ -+instruct vsqrtF(vReg dst, vReg src) %{ -+ match(Set dst (SqrtVF src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsqrt.v $dst, $src\t#@vsqrtF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsqrtD(vReg dst, vReg src) %{ -+ match(Set dst (SqrtVD src)); -+ ins_cost(VEC_COST); -+ format %{ "vfsqrt.v $dst, $src\t#@vsqrtD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+// vector sub -+ -+instruct vsubB(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVB src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vsub.vv $dst, $src1, $src2\t#@vsubB" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e8); -+ __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsubS(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVS src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vsub.vv $dst, $src1, $src2\t#@vsubS" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e16); -+ __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsubI(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVI src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vsub.vv $dst, $src1, $src2\t#@vsubI" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsubL(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVL src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vsub.vv $dst, $src1, $src2\t#@vsubL" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsubF(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVF src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfsub.vv $dst, $src1, $src2\t@vsubF" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e32); -+ __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vsubD(vReg dst, vReg src1, vReg src2) %{ -+ match(Set dst (SubVD src1 src2)); -+ ins_cost(VEC_COST); -+ format %{ "vfsub.vv $dst, $src1, $src2\t#@vsubD" %} -+ ins_encode %{ -+ __ vsetvli(t0, x0, Assembler::e64); -+ __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -+ as_VectorRegister($src2$$reg)); -+ %} -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vstring_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, -+ iRegI_R10 result, vReg_V1 v1, -+ vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) -+%{ -+ predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); -+ match(Set result (StrEquals (Binary str1 str2) cnt)); -+ effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); -+ -+ format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsL" %} -+ ins_encode %{ -+ // Count is in 8-bit bytes; non-Compact chars are 16 bits. -+ __ string_equals_v($str1$$Register, $str2$$Register, -+ $result$$Register, $cnt$$Register, 1); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct vstring_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, -+ iRegI_R10 result, vReg_V1 v1, -+ vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) -+%{ -+ predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); -+ match(Set result (StrEquals (Binary str1 str2) cnt)); -+ effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); -+ -+ format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %} -+ ins_encode %{ -+ // Count is in 8-bit bytes; non-Compact chars are 16 bits. -+ __ string_equals_v($str1$$Register, $str2$$Register, -+ $result$$Register, $cnt$$Register, 2); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct varray_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) -+%{ -+ predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); -+ match(Set result (AryEq ary1 ary2)); -+ effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); -+ -+ format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsB // KILL $tmp" %} -+ ins_encode %{ -+ __ arrays_equals_v($ary1$$Register, $ary2$$Register, -+ $result$$Register, $tmp$$Register, 1); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct varray_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) -+%{ -+ predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); -+ match(Set result (AryEq ary1 ary2)); -+ effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); -+ -+ format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsC // KILL $tmp" %} -+ ins_encode %{ -+ __ arrays_equals_v($ary1$$Register, $ary2$$Register, -+ $result$$Register, $tmp$$Register, 2); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct vstring_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -+ iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -+ iRegP_R28 tmp1, iRegL_R29 tmp2) -+%{ -+ predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); -+ match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -+ TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -+ -+ format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareU" %} -+ ins_encode %{ -+ // Count is in 8-bit bytes; non-Compact chars are 16 bits. -+ __ string_compare_v($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ $tmp1$$Register, $tmp2$$Register, -+ StrIntrinsicNode::UU); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+instruct vstring_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -+ iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -+ iRegP_R28 tmp1, iRegL_R29 tmp2) -+%{ -+ predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); -+ match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -+ TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -+ -+ format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareL" %} -+ ins_encode %{ -+ __ string_compare_v($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ $tmp1$$Register, $tmp2$$Register, -+ StrIntrinsicNode::LL); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct vstring_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -+ iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -+ iRegP_R28 tmp1, iRegL_R29 tmp2) -+%{ -+ predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); -+ match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -+ TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -+ -+ format %{"String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareUL" %} -+ ins_encode %{ -+ __ string_compare_v($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ $tmp1$$Register, $tmp2$$Register, -+ StrIntrinsicNode::UL); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+instruct vstring_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -+ iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -+ iRegP_R28 tmp1, iRegL_R29 tmp2) -+%{ -+ predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); -+ match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -+ effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -+ TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -+ -+ format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareLU" %} -+ ins_encode %{ -+ __ string_compare_v($str1$$Register, $str2$$Register, -+ $cnt1$$Register, $cnt2$$Register, $result$$Register, -+ $tmp1$$Register, $tmp2$$Register, -+ StrIntrinsicNode::LU); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+// fast byte[] to char[] inflation -+instruct vstring_inflate(Universe dummy, iRegP_R10 src, iRegP_R11 dst, iRegI_R12 len, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) -+%{ -+ predicate(UseRVV); -+ match(Set dummy (StrInflatedCopy src (Binary dst len))); -+ effect(TEMP v1, TEMP v2, TEMP v3, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len); -+ -+ format %{ "String Inflate $src,$dst" %} -+ ins_encode %{ -+ __ byte_array_inflate_v($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register); -+ %} -+ ins_pipe(pipe_class_memory); -+%} -+ -+// encode char[] to byte[] in ISO_8859_1 -+instruct vencode_iso_array(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) -+%{ -+ predicate(UseRVV); -+ match(Set result (EncodeISOArray src (Binary dst len))); -+ effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, -+ TEMP v1, TEMP v2, TEMP v3, TEMP tmp); -+ -+ format %{ "Encode array $src,$dst,$len -> $result" %} -+ ins_encode %{ -+ __ encode_iso_array_v($src$$Register, $dst$$Register, $len$$Register, -+ $result$$Register, $tmp$$Register); -+ %} -+ ins_pipe( pipe_class_memory ); -+%} -+ -+// fast char[] to byte[] compression -+instruct vstring_compress(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) -+%{ -+ predicate(UseRVV); -+ match(Set result (StrCompressedCopy src (Binary dst len))); -+ effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, -+ TEMP v1, TEMP v2, TEMP v3, TEMP tmp); -+ -+ format %{ "String Compress $src,$dst -> $result // KILL R11, R12, R13" %} -+ ins_encode %{ -+ __ char_array_compress_v($src$$Register, $dst$$Register, $len$$Register, -+ $result$$Register, $tmp$$Register); -+ %} -+ ins_pipe( pipe_slow ); -+%} -+ -+instruct vcount_positives(iRegP_R11 ary, iRegI_R12 len, iRegI_R10 result, iRegL tmp) -+%{ -+ predicate(UseRVV); -+ match(Set result (CountPositives ary len)); -+ effect(USE_KILL ary, USE_KILL len, TEMP tmp); -+ -+ format %{ "count positives byte[] $ary, $len -> $result" %} -+ ins_encode %{ -+ __ count_positives_v($ary$$Register, $len$$Register, $result$$Register, $tmp$$Register); -+ %} -+ -+ ins_pipe(pipe_slow); -+%} -+ -+instruct vstringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -+ iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) -+%{ -+ predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); -+ match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, -+ TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); -+ -+ format %{ "StringUTF16 IndexOf char[] $str1, $cnt1, $ch -> $result" %} -+ -+ ins_encode %{ -+ __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, -+ $result$$Register, $tmp1$$Register, $tmp2$$Register, -+ false /* isL */); -+ %} -+ -+ ins_pipe(pipe_class_memory); -+%} -+ -+instruct vstringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -+ iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -+ vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) -+%{ -+ predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); -+ match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -+ effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, -+ TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); -+ -+ format %{ "StringLatin1 IndexOf char[] $str1, $cnt1, $ch -> $result" %} -+ -+ ins_encode %{ -+ __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, -+ $result$$Register, $tmp1$$Register, $tmp2$$Register, -+ true /* isL */); -+ %} -+ -+ ins_pipe(pipe_class_memory); -+%} -+ -+// clearing of an array -+instruct vclearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy, -+ vReg_V1 vReg1, vReg_V2 vReg2, vReg_V3 vReg3) -+%{ -+ predicate(UseRVV); -+ match(Set dummy (ClearArray cnt base)); -+ effect(USE_KILL cnt, USE_KILL base, TEMP vReg1, TEMP vReg2, TEMP vReg3); -+ -+ format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %} -+ -+ ins_encode %{ -+ __ clear_array_v($base$$Register, $cnt$$Register); -+ %} -+ -+ ins_pipe(pipe_class_memory); -+%} diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp new file mode 100644 -index 00000000000..f85d4b25a76 +index 0000000000..7b1112b388 --- /dev/null +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -0,0 +1,2761 @@ +@@ -0,0 +1,2661 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -43146,9 +38562,8 @@ index 00000000000..f85d4b25a76 +}; + +class RegisterSaver { -+ const bool _save_vectors; + public: -+ RegisterSaver(bool save_vectors) : _save_vectors(UseRVV && save_vectors) {} ++ RegisterSaver() {} + ~RegisterSaver() {} + OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); + void restore_live_registers(MacroAssembler* masm); @@ -43157,11 +38572,7 @@ index 00000000000..f85d4b25a76 + // Used by deoptimization when it is managing result register + // values on its own + // gregs:28, float_register:32; except: x1(ra) & x2(sp) & gp(x3) & tp(x4) -+ // |---v0---|<---SP -+ // |---v1---|save vectors only in generate_handler_blob -+ // |-- .. --| -+ // |---v31--|----- -+ // |---f0---| ++ // |---f0---|<---SP + // |---f1---| + // | .. | + // |---f31--| @@ -43172,16 +38583,8 @@ index 00000000000..f85d4b25a76 + // |---x31--| + // |---fp---| + // |---ra---| -+ int v0_offset_in_bytes(void) { return 0; } + int f0_offset_in_bytes(void) { -+ int f0_offset = 0; -+#ifdef COMPILER2 -+ if (_save_vectors) { -+ f0_offset += Matcher::scalable_vector_reg_size(T_INT) * VectorRegisterImpl::number_of_registers * -+ BytesPerInt; -+ } -+#endif -+ return f0_offset; ++ return 0; + } + int reserved_slot_offset_in_bytes(void) { + return f0_offset_in_bytes() + @@ -43208,16 +38611,6 @@ index 00000000000..f85d4b25a76 +}; + +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { -+ int vector_size_in_bytes = 0; -+ int vector_size_in_slots = 0; -+#ifdef COMPILER2 -+ if (_save_vectors) { -+ vector_size_in_bytes += Matcher::scalable_vector_reg_size(T_BYTE); -+ vector_size_in_slots += Matcher::scalable_vector_reg_size(T_INT); -+ } -+#endif -+ -+ assert_cond(masm != NULL && total_frame_words != NULL); + int frame_size_in_bytes = align_up(additional_frame_words * wordSize + ra_offset_in_bytes() + wordSize, 16); + // OopMap frame size is in compiler stack slots (jint's) not bytes or words + int frame_size_in_slots = frame_size_in_bytes / BytesPerInt; @@ -43227,9 +38620,9 @@ index 00000000000..f85d4b25a76 + int frame_size_in_words = frame_size_in_bytes / wordSize; + *total_frame_words = frame_size_in_words; + -+ // Save Integer, Float and Vector registers. ++ // Save Integer and Float registers. + __ enter(); -+ __ push_CPU_state(_save_vectors, vector_size_in_bytes); ++ __ push_CPU_state(); + + // Set an oopmap for the call site. This oopmap will map all + // oop-registers and debug-info registers as callee-saved. This @@ -43242,13 +38635,6 @@ index 00000000000..f85d4b25a76 + + int sp_offset_in_slots = 0; + int step_in_slots = 0; -+ if (_save_vectors) { -+ step_in_slots = vector_size_in_slots; -+ for (int i = 0; i < VectorRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { -+ VectorRegister r = as_VectorRegister(i); -+ oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset_in_slots), r->as_VMReg()); -+ } -+ } + + step_in_slots = FloatRegisterImpl::max_slots_per_register; + for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { @@ -43272,19 +38658,23 @@ index 00000000000..f85d4b25a76 +} + +void RegisterSaver::restore_live_registers(MacroAssembler* masm) { -+ assert_cond(masm != NULL); -+#ifdef COMPILER2 -+ __ pop_CPU_state(_save_vectors, Matcher::scalable_vector_reg_size(T_BYTE)); -+#else -+ __ pop_CPU_state(_save_vectors); -+#endif ++ __ pop_CPU_state(); + __ leave(); +} + +// Is vector's size (in bytes) bigger than a size saved by default? -+// riscv does not ovlerlay the floating-point registers on vector registers like aarch64. +bool SharedRuntime::is_wide_vector(int size) { -+ return UseRVV; ++ return false; ++} ++ ++size_t SharedRuntime::trampoline_size() { ++ return 6 * NativeInstruction::instruction_size; ++} ++ ++void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { ++ int32_t offset = 0; ++ __ movptr_with_offset(t0, destination, offset); ++ __ jalr(x0, t0, offset); +} + +// The java_calling_convention describes stack locations as ideal slots on @@ -43323,7 +38713,8 @@ index 00000000000..f85d4b25a76 + +int SharedRuntime::java_calling_convention(const BasicType *sig_bt, + VMRegPair *regs, -+ int total_args_passed) { ++ int total_args_passed, ++ int is_outgoing) { + // Create the mapping between argument positions and + // registers. + static const Register INT_ArgReg[Argument::n_int_register_parameters_j] = { @@ -43397,7 +38788,6 @@ index 00000000000..f85d4b25a76 + +// Patch the callers callsite with entry to compiled code if it exists. +static void patch_callers_callsite(MacroAssembler *masm) { -+ assert_cond(masm != NULL); + Label L; + __ ld(t0, Address(xmethod, in_bytes(Method::code_offset()))); + __ beqz(t0, L); @@ -43420,10 +38810,6 @@ index 00000000000..f85d4b25a76 + __ la_patchable(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite)), offset); + __ jalr(x1, t0, offset); + -+ // Explicit fence.i required because fixup_callers_callsite may change the code -+ // stream. -+ __ safepoint_ifence(); -+ + __ pop_CPU_state(); + // restore sp + __ leave(); @@ -43510,7 +38896,7 @@ index 00000000000..f85d4b25a76 + __ sd(t0, Address(sp, next_off), /*temp register*/esp); +#ifdef ASSERT + // Overwrite the unused slot with known junk -+ __ li(t0, 0xdeadffffdeadaaaaul); ++ __ mv(t0, 0xdeadffffdeadaaaaul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + } else { @@ -43529,7 +38915,7 @@ index 00000000000..f85d4b25a76 + // long/double in gpr +#ifdef ASSERT + // Overwrite the unused slot with known junk -+ __ li(t0, 0xdeadffffdeadaaabul); ++ __ mv(t0, 0xdeadffffdeadaaabul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + __ sd(r, Address(sp, next_off)); @@ -43545,7 +38931,7 @@ index 00000000000..f85d4b25a76 + } else { +#ifdef ASSERT + // Overwrite the unused slot with known junk -+ __ li(t0, 0xdeadffffdeadaaacul); ++ __ mv(t0, 0xdeadffffdeadaaacul); + __ sd(t0, Address(sp, st_off), /*temp register*/esp); +#endif /* ASSERT */ + __ fsd(r_1->as_FloatRegister(), Address(sp, next_off)); @@ -43712,39 +39098,10 @@ index 00000000000..f85d4b25a76 + + address c2i_entry = __ pc(); + -+ // Class initialization barrier for static methods -+ address c2i_no_clinit_check_entry = NULL; -+ if (VM_Version::supports_fast_class_init_checks()) { -+ Label L_skip_barrier; -+ -+ { // Bypass the barrier for non-static methods -+ __ lwu(t0, Address(xmethod, Method::access_flags_offset())); -+ __ andi(t1, t0, JVM_ACC_STATIC); -+ __ beqz(t1, L_skip_barrier); // non-static -+ } -+ -+ __ load_method_holder(t1, xmethod); -+ __ clinit_barrier(t1, t0, &L_skip_barrier); -+ __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -+ -+ __ bind(L_skip_barrier); -+ c2i_no_clinit_check_entry = __ pc(); -+ } -+ -+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ bs->c2i_entry_barrier(masm); -+ + gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); + + __ flush(); -+ return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); -+} -+ -+int SharedRuntime::vector_calling_convention(VMRegPair *regs, -+ uint num_bits, -+ uint total_args_passed) { -+ Unimplemented(); -+ return 0; ++ return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); +} + +int SharedRuntime::c_calling_convention(const BasicType *sig_bt, @@ -43829,16 +39186,21 @@ index 00000000000..f85d4b25a76 + return stk_args; +} + -+// On 64 bit we will store integer like items to the stack as -+// 64 bits items (riscv64 abi) even though java would only store -+// 32bits for a parameter. On 32bit it will simply be 32 bits -+// So this routine will do 32->32 on 32bit and 32->64 on 64bit ++// The C ABI specifies: ++// "integer scalars narrower than XLEN bits are widened according to the sign ++// of their type up to 32 bits, then sign-extended to XLEN bits." ++// Applies for both passed in register and stack. ++// ++// Java uses 32-bit stack slots; jint, jshort, jchar, jbyte uses one slot. ++// Native uses 64-bit stack slots for all integer scalar types. ++// ++// lw loads the Java stack slot, sign-extends and ++// sd store this widened integer into a 64 bit native stack slot. +static void move32_64(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { -+ assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack -+ __ ld(t0, Address(fp, reg2offset_in(src.first()))); ++ __ lw(t0, Address(fp, reg2offset_in(src.first()))); + __ sd(t0, Address(sp, reg2offset_out(dst.first()))); + } else { + // stack to reg @@ -43864,7 +39226,6 @@ index 00000000000..f85d4b25a76 + VMRegPair dst, + bool is_receiver, + int* receiver_offset) { -+ assert_cond(masm != NULL && map != NULL && receiver_offset != NULL); + // must pass a handle. First figure out the location we use as a handle + Register rHandle = dst.first()->is_stack() ? t1 : dst.first()->as_Register(); + @@ -43947,7 +39308,6 @@ index 00000000000..f85d4b25a76 +static void float_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert(src.first()->is_stack() && dst.first()->is_stack() || + src.first()->is_reg() && dst.first()->is_reg() || src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); -+ assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + __ lwu(t0, Address(fp, reg2offset_in(src.first()))); @@ -43968,7 +39328,6 @@ index 00000000000..f85d4b25a76 + +// A long move +static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { -+ assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack @@ -43992,7 +39351,6 @@ index 00000000000..f85d4b25a76 +static void double_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + assert(src.first()->is_stack() && dst.first()->is_stack() || + src.first()->is_reg() && dst.first()->is_reg() || src.first()->is_stack() && dst.first()->is_reg(), "Unexpected error"); -+ assert_cond(masm != NULL); + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + __ ld(t0, Address(fp, reg2offset_in(src.first()))); @@ -44012,7 +39370,6 @@ index 00000000000..f85d4b25a76 +} + +void SharedRuntime::save_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { -+ assert_cond(masm != NULL); + // We always ignore the frame_slots arg and just use the space just below frame pointer + // which by this time is free to use + switch (ret_type) { @@ -44030,7 +39387,6 @@ index 00000000000..f85d4b25a76 +} + +void SharedRuntime::restore_native_result(MacroAssembler *masm, BasicType ret_type, int frame_slots) { -+ assert_cond(masm != NULL); + // We always ignore the frame_slots arg and just use the space just below frame pointer + // which by this time is free to use + switch (ret_type) { @@ -44048,7 +39404,6 @@ index 00000000000..f85d4b25a76 +} + +static void save_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) { -+ assert_cond(masm != NULL && args != NULL); + RegSet x; + for ( int i = first_arg ; i < arg_count ; i++ ) { + if (args[i].first()->is_Register()) { @@ -44062,7 +39417,6 @@ index 00000000000..f85d4b25a76 +} + +static void restore_args(MacroAssembler *masm, int arg_count, int first_arg, VMRegPair *args) { -+ assert_cond(masm != NULL && args != NULL); + RegSet x; + for ( int i = first_arg ; i < arg_count ; i++ ) { + if (args[i].first()->is_Register()) { @@ -44083,7 +39437,6 @@ index 00000000000..f85d4b25a76 +} + +static void rt_call(MacroAssembler* masm, address dest) { -+ assert_cond(masm != NULL); + CodeBlob *cb = CodeCache::find_blob(dest); + if (cb) { + __ far_call(RuntimeAddress(dest)); @@ -44133,10 +39486,10 @@ index 00000000000..f85d4b25a76 + member_arg_pos = method->size_of_parameters() - 1; // trailing MemberName argument + member_reg = x9; // known to be free at this point + has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); -+ } else if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { ++ } else if (iid == vmIntrinsics::_invokeBasic) { + has_receiver = true; + } else { -+ fatal("unexpected intrinsic id %d", vmIntrinsics::as_int(iid)); ++ fatal("unexpected intrinsic id %d", iid); + } + + if (member_reg != noreg) { @@ -44208,13 +39561,15 @@ index 00000000000..f85d4b25a76 + int compile_id, + BasicType* in_sig_bt, + VMRegPair* in_regs, -+ BasicType ret_type) { ++ BasicType ret_type, ++ address critical_entry) { + if (method->is_method_handle_intrinsic()) { + vmIntrinsics::ID iid = method->intrinsic_id(); + intptr_t start = (intptr_t)__ pc(); + int vep_offset = ((intptr_t)__ pc()) - start; + + // First instruction must be a nop as it may need to be patched on deoptimisation ++ MacroAssembler::assert_alignment(__ pc()); + __ nop(); + gen_special_dispatch(masm, + method, @@ -44366,29 +39721,17 @@ index 00000000000..f85d4b25a76 + + // If we have to make this method not-entrant we'll overwrite its + // first instruction with a jump. ++ MacroAssembler::assert_alignment(__ pc()); + __ nop(); + -+ if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) { -+ Label L_skip_barrier; -+ __ mov_metadata(t1, method->method_holder()); // InstanceKlass* -+ __ clinit_barrier(t1, t0, &L_skip_barrier); -+ __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -+ -+ __ bind(L_skip_barrier); -+ } -+ + // Generate stack overflow check -+ __ bang_stack_with_offset(checked_cast(StackOverflow::stack_shadow_zone_size())); ++ __ bang_stack_with_offset((int)JavaThread::stack_shadow_zone_size()); + + // Generate a new frame for the wrapper. + __ enter(); + // -2 because return address is already present and so is saved fp + __ sub(sp, sp, stack_size - 2 * wordSize); + -+ BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -+ assert_cond(bs != NULL); -+ bs->nmethod_entry_barrier(masm); -+ + // Frame is now completed as far as size and linkage. + int frame_complete = ((intptr_t)__ pc()) - start; + @@ -44585,39 +39928,39 @@ index 00000000000..f85d4b25a76 + // Load the oop from the handle + __ ld(obj_reg, Address(oop_handle_reg, 0)); + -+ if (!UseHeavyMonitors) { -+ // Load (object->mark() | 1) into swap_reg % x10 -+ __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); -+ __ ori(swap_reg, t0, 1); -+ -+ // Save (object->mark() | 1) into BasicLock's displaced header -+ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -+ -+ // src -> dest if dest == x10 else x10 <- dest -+ { -+ Label here; -+ __ cmpxchg_obj_header(x10, lock_reg, obj_reg, t0, lock_done, /*fallthrough*/NULL); -+ } -+ -+ // Test if the oopMark is an obvious stack pointer, i.e., -+ // 1) (mark & 3) == 0, and -+ // 2) sp <= mark < mark + os::pagesize() -+ // These 3 tests can be done by evaluating the following -+ // expression: ((mark - sp) & (3 - os::vm_page_size())), -+ // assuming both stack pointer and pagesize have their -+ // least significant 2 bits clear. -+ // NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg -+ -+ __ sub(swap_reg, swap_reg, sp); -+ __ andi(swap_reg, swap_reg, 3 - os::vm_page_size()); -+ -+ // Save the test result, for recursive case, the result is zero -+ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -+ __ bnez(swap_reg, slow_path_lock); -+ } else { -+ __ j(slow_path_lock); ++ if (UseBiasedLocking) { ++ __ biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp, false, lock_done, &slow_path_lock); + } + ++ // Load (object->mark() | 1) into swap_reg % x10 ++ __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); ++ __ ori(swap_reg, t0, 1); ++ ++ // Save (object->mark() | 1) into BasicLock's displaced header ++ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); ++ ++ // src -> dest if dest == x10 else x10 <- dest ++ { ++ Label here; ++ __ cmpxchg_obj_header(x10, lock_reg, obj_reg, t0, lock_done, /*fallthrough*/NULL); ++ } ++ ++ // Test if the oopMark is an obvious stack pointer, i.e., ++ // 1) (mark & 3) == 0, and ++ // 2) sp <= mark < mark + os::pagesize() ++ // These 3 tests can be done by evaluating the following ++ // expression: ((mark - sp) & (3 - os::vm_page_size())), ++ // assuming both stack pointer and pagesize have their ++ // least significant 2 bits clear. ++ // NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg ++ ++ __ sub(swap_reg, swap_reg, sp); ++ __ andi(swap_reg, swap_reg, 3 - os::vm_page_size()); ++ ++ // Save the test result, for recursive case, the result is zero ++ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); ++ __ bnez(swap_reg, slow_path_lock); ++ + // Slow path will re-enter here + __ bind(lock_done); + } @@ -44665,15 +40008,7 @@ index 00000000000..f85d4b25a76 + + // check for safepoint operation in progress and/or pending suspend requests + { -+ // We need an acquire here to ensure that any subsequent load of the -+ // global SafepointSynchronize::_state flag is ordered after this load -+ // of the thread-local polling word. We don't want this poll to -+ // return false (i.e. not safepointing) and a later poll of the global -+ // SafepointSynchronize::_state spuriously to return true. -+ // This is to avoid a race when we're in a native->Java transition -+ // racing the code which wakes up from a safepoint. -+ -+ __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); ++ __ safepoint_poll_acquire(safepoint_in_progress); + __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); + __ bnez(t0, safepoint_in_progress); + __ bind(safepoint_in_progress_done); @@ -44689,7 +40024,7 @@ index 00000000000..f85d4b25a76 + Label reguard; + Label reguard_done; + __ lbu(t0, Address(xthread, JavaThread::stack_guard_state_offset())); -+ __ mv(t1, StackOverflow::stack_guard_yellow_reserved_disabled); ++ __ mv(t1, JavaThread::stack_guard_yellow_reserved_disabled); + __ beq(t0, t1, reguard); + __ bind(reguard_done); + @@ -44705,31 +40040,28 @@ index 00000000000..f85d4b25a76 + + Label done; + -+ if (!UseHeavyMonitors) { -+ // Simple recursive lock? -+ __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -+ __ beqz(t0, done); ++ if (UseBiasedLocking) { ++ __ biased_locking_exit(obj_reg, old_hdr, done); + } + ++ // Simple recursive lock? ++ __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); ++ __ beqz(t0, done); + + // Must save x10 if if it is live now because cmpxchg must use it + if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { + save_native_result(masm, ret_type, stack_slots); + } + -+ if (!UseHeavyMonitors) { -+ // get address of the stack lock -+ __ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -+ // get old displaced header -+ __ ld(old_hdr, Address(x10, 0)); ++ // get address of the stack lock ++ __ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); ++ // get old displaced header ++ __ ld(old_hdr, Address(x10, 0)); + -+ // Atomic swap old header if oop still contains the stack lock -+ Label succeed; -+ __ cmpxchg_obj_header(x10, old_hdr, obj_reg, t0, succeed, &slow_path_unlock); -+ __ bind(succeed); -+ } else { -+ __ j(slow_path_unlock); -+ } ++ // Atomic swap old header if oop still contains the stack lock ++ Label succeed; ++ __ cmpxchg_obj_header(x10, old_hdr, obj_reg, t0, succeed, &slow_path_unlock); ++ __ bind(succeed); + + // slow path re-enters here + __ bind(unlock_done); @@ -44957,7 +40289,7 @@ index 00000000000..f85d4b25a76 + OopMap* map = NULL; + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(masm != NULL && oop_maps != NULL); -+ RegisterSaver reg_saver(COMPILER2_OR_JVMCI != 0); ++ RegisterSaver reg_saver; + + // ------------- + // This code enters when returning to a de-optimized nmethod. A return @@ -45049,7 +40381,7 @@ index 00000000000..f85d4b25a76 + // Now it is safe to overwrite any register + + // Deopt during an exception. Save exec mode for unpack_frames. -+ __ li(xcpool, Deoptimization::Unpack_exception); // callee-saved ++ __ mv(xcpool, Deoptimization::Unpack_exception); // callee-saved + + // load throwing pc from JavaThread and patch it as the return address + // of the current frame. Then clear the field in JavaThread @@ -45110,7 +40442,7 @@ index 00000000000..f85d4b25a76 + + __ lwu(xcpool, Address(x15, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes())); + Label noException; -+ __ li(t0, Deoptimization::Unpack_exception); ++ __ mv(t0, Deoptimization::Unpack_exception); + __ bne(xcpool, t0, noException); // Was exception pending? + __ ld(x10, Address(xthread, JavaThread::exception_oop_offset())); + __ ld(x13, Address(xthread, JavaThread::exception_pc_offset())); @@ -45189,7 +40521,7 @@ index 00000000000..f85d4b25a76 + __ sub(sp, sp, x9); + + // Push interpreter frames in a loop -+ __ li(t0, 0xDEADDEAD); // Make a recognizable pattern ++ __ mv(t0, 0xDEADDEAD); // Make a recognizable pattern + __ mv(t1, t0); + Label loop; + __ bind(loop); @@ -45262,14 +40594,6 @@ index 00000000000..f85d4b25a76 + _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); +} + -+// Number of stack slots between incoming argument block and the start of -+// a new frame. The PROLOG must add this many slots to the stack. The -+// EPILOG must remove this many slots. -+// RISCV needs two words for RA (return address) and FP (frame pointer). -+uint SharedRuntime::in_preserve_stack_slots() { -+ return 2 * VMRegImpl::slots_per_word; -+} -+ +uint SharedRuntime::out_preserve_stack_slots() { + return 0; +} @@ -45489,7 +40813,7 @@ index 00000000000..f85d4b25a76 + address call_pc = NULL; + int frame_size_in_words = -1; + bool cause_return = (poll_type == POLL_AT_RETURN); -+ RegisterSaver reg_saver(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); ++ RegisterSaver reg_saver; + + // Save Integer and Float registers. + map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); @@ -45546,7 +40870,7 @@ index 00000000000..f85d4b25a76 + __ bind(noException); + + Label no_adjust, bail; -+ if (!cause_return) { ++ if (SafepointMechanism::uses_thread_local_poll() && !cause_return) { + // If our stashed return pc was modified by the runtime we avoid touching it + __ ld(t0, Address(fp, frame::return_addr_offset * wordSize)); + __ bne(x18, t0, no_adjust); @@ -45598,7 +40922,7 @@ index 00000000000..f85d4b25a76 +// must do any gc of the args. +// +RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const char* name) { -+ assert (StubRoutines::forward_exception_entry() != NULL, "must be generated before"); ++ assert(StubRoutines::forward_exception_entry() != NULL, "must be generated before"); + + // allocate space for the code + ResourceMark rm; @@ -45608,7 +40932,7 @@ index 00000000000..f85d4b25a76 + assert_cond(masm != NULL); + + int frame_size_in_words = -1; -+ RegisterSaver reg_saver(false /* save_vectors */); ++ RegisterSaver reg_saver; + + OopMapSet *oop_maps = new OopMapSet(); + assert_cond(oop_maps != NULL); @@ -45680,14 +41004,6 @@ index 00000000000..f85d4b25a76 +} + +#ifdef COMPILER2 -+RuntimeStub* SharedRuntime::make_native_invoker(address call_target, -+ int shadow_space_bytes, -+ const GrowableArray& input_registers, -+ const GrowableArray& output_registers) { -+ Unimplemented(); -+ return nullptr; -+} -+ +//------------------------------generate_exception_blob--------------------------- +// creates exception blob at the end +// Using exception blob, this code is jumped from a compiled method. @@ -45827,10 +41143,10 @@ index 00000000000..f85d4b25a76 +#endif // COMPILER2 diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp new file mode 100644 -index 00000000000..b3fdd04db1b +index 0000000000..272dd9aeb3 --- /dev/null +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -0,0 +1,3864 @@ +@@ -0,0 +1,3743 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -45878,7 +41194,6 @@ index 00000000000..b3fdd04db1b +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/align.hpp" -+#include "utilities/powerOfTwo.hpp" +#ifdef COMPILER2 +#include "opto/runtime.hpp" +#endif @@ -45952,16 +41267,28 @@ index 00000000000..b3fdd04db1b + // we don't need to save x6-x7 and x28-x31 which both C and Java treat as + // volatile + // -+ // we save x18-x27 which Java uses as temporary registers and C -+ // expects to be callee-save ++ // we save x9, x18-x27, f8-f9, and f18-f27 which Java uses as temporary ++ // registers and C expects to be callee-save + // + // so the stub frame looks like this when we enter Java code + // + // [ return_from_Java ] <--- sp + // [ argument word n ] + // ... -+ // -22 [ argument word 1 ] -+ // -21 [ saved x27 ] <--- sp_after_call ++ // -34 [ argument word 1 ] ++ // -33 [ saved f27 ] <--- sp_after_call ++ // -32 [ saved f26 ] ++ // -31 [ saved f25 ] ++ // -30 [ saved f24 ] ++ // -29 [ saved f23 ] ++ // -28 [ saved f22 ] ++ // -27 [ saved f21 ] ++ // -26 [ saved f20 ] ++ // -25 [ saved f19 ] ++ // -24 [ saved f18 ] ++ // -23 [ saved f9 ] ++ // -22 [ saved f8 ] ++ // -21 [ saved x27 ] + // -20 [ saved x26 ] + // -19 [ saved x25 ] + // -18 [ saved x24 ] @@ -45986,7 +41313,20 @@ index 00000000000..b3fdd04db1b + + // Call stub stack layout word offsets from fp + enum call_stub_layout { -+ sp_after_call_off = -21, ++ sp_after_call_off = -33, ++ ++ f27_off = -33, ++ f26_off = -32, ++ f25_off = -31, ++ f24_off = -30, ++ f23_off = -29, ++ f22_off = -28, ++ f21_off = -27, ++ f20_off = -26, ++ f19_off = -25, ++ f18_off = -24, ++ f9_off = -23, ++ f8_off = -22, + + x27_off = -21, + x26_off = -20, @@ -46032,6 +41372,19 @@ index 00000000000..b3fdd04db1b + + const Address thread (fp, thread_off * wordSize); + ++ const Address f27_save (fp, f27_off * wordSize); ++ const Address f26_save (fp, f26_off * wordSize); ++ const Address f25_save (fp, f25_off * wordSize); ++ const Address f24_save (fp, f24_off * wordSize); ++ const Address f23_save (fp, f23_off * wordSize); ++ const Address f22_save (fp, f22_off * wordSize); ++ const Address f21_save (fp, f21_off * wordSize); ++ const Address f20_save (fp, f20_off * wordSize); ++ const Address f19_save (fp, f19_off * wordSize); ++ const Address f18_save (fp, f18_off * wordSize); ++ const Address f9_save (fp, f9_off * wordSize); ++ const Address f8_save (fp, f8_off * wordSize); ++ + const Address x27_save (fp, x27_off * wordSize); + const Address x26_save (fp, x26_off * wordSize); + const Address x25_save (fp, x25_off * wordSize); @@ -46078,6 +41431,19 @@ index 00000000000..b3fdd04db1b + __ sd(x26, x26_save); + __ sd(x27, x27_save); + ++ __ fsd(f8, f8_save); ++ __ fsd(f9, f9_save); ++ __ fsd(f18, f18_save); ++ __ fsd(f19, f19_save); ++ __ fsd(f20, f20_save); ++ __ fsd(f21, f21_save); ++ __ fsd(f22, f22_save); ++ __ fsd(f23, f23_save); ++ __ fsd(f24, f24_save); ++ __ fsd(f25, f25_save); ++ __ fsd(f26, f26_save); ++ __ fsd(f27, f27_save); ++ + // install Java thread in global register now we have saved + // whatever value it held + __ mv(xthread, c_rarg7); @@ -46137,13 +41503,13 @@ index 00000000000..b3fdd04db1b + __ ld(j_rarg2, result); + Label is_long, is_float, is_double, exit; + __ ld(j_rarg1, result_type); -+ __ li(t0, (u1)T_OBJECT); ++ __ mv(t0, (u1)T_OBJECT); + __ beq(j_rarg1, t0, is_long); -+ __ li(t0, (u1)T_LONG); ++ __ mv(t0, (u1)T_LONG); + __ beq(j_rarg1, t0, is_long); -+ __ li(t0, (u1)T_FLOAT); ++ __ mv(t0, (u1)T_FLOAT); + __ beq(j_rarg1, t0, is_float); -+ __ li(t0, (u1)T_DOUBLE); ++ __ mv(t0, (u1)T_DOUBLE); + __ beq(j_rarg1, t0, is_double); + + // handle T_INT case @@ -46169,6 +41535,19 @@ index 00000000000..b3fdd04db1b +#endif + + // restore callee-save registers ++ __ fld(f27, f27_save); ++ __ fld(f26, f26_save); ++ __ fld(f25, f25_save); ++ __ fld(f24, f24_save); ++ __ fld(f23, f23_save); ++ __ fld(f22, f22_save); ++ __ fld(f21, f21_save); ++ __ fld(f20, f20_save); ++ __ fld(f19, f19_save); ++ __ fld(f18, f18_save); ++ __ fld(f9, f9_save); ++ __ fld(f8, f8_save); ++ + __ ld(x27, x27_save); + __ ld(x26, x26_save); + __ ld(x25, x25_save); @@ -46368,7 +41747,7 @@ index 00000000000..b3fdd04db1b + + Label exit, error; + -+ __ push_reg(0x3000, sp); // save c_rarg2 and c_rarg3 ++ __ push_reg(RegSet::of(c_rarg2, c_rarg3), sp); // save c_rarg2 and c_rarg3 + + __ la(c_rarg2, ExternalAddress((address) StubRoutines::verify_oop_count_addr())); + __ ld(c_rarg3, Address(c_rarg2)); @@ -46379,16 +41758,6 @@ index 00000000000..b3fdd04db1b + // make sure object is 'reasonable' + __ beqz(x10, exit); // if obj is NULL it is OK + -+#if INCLUDE_ZGC -+ if (UseZGC) { -+ // Check if mask is good. -+ // verifies that ZAddressBadMask & x10 == 0 -+ __ ld(c_rarg3, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -+ __ andr(c_rarg2, x10, c_rarg3); -+ __ bnez(c_rarg2, error); -+ } -+#endif -+ + // Check if the oop is in the right area of memory + __ mv(c_rarg3, (intptr_t) Universe::verify_oop_mask()); + __ andr(c_rarg2, x10, c_rarg3); @@ -46404,12 +41773,12 @@ index 00000000000..b3fdd04db1b + // return if everything seems ok + __ bind(exit); + -+ __ pop_reg(0x3000, sp); // pop c_rarg2 and c_rarg3 ++ __ pop_reg(RegSet::of(c_rarg2, c_rarg3), sp); // pop c_rarg2 and c_rarg3 + __ ret(); + + // handle errors + __ bind(error); -+ __ pop_reg(0x3000, sp); // pop c_rarg2 and c_rarg3 ++ __ pop_reg(RegSet::of(c_rarg2, c_rarg3), sp); // pop c_rarg2 and c_rarg3 + + __ pusha(); + // debug(char* msg, int64_t pc, int64_t regs[]) @@ -46522,7 +41891,7 @@ index 00000000000..b3fdd04db1b + { + Label L; + -+ __ li(t0, 8); ++ __ mv(t0, 8); + __ bge(count, t0, L); + __ stop("genrate_copy_longs called with < 8 words"); + __ bind(L); @@ -46892,12 +42261,7 @@ index 00000000000..b3fdd04db1b + __ push_reg(RegSet::of(d, count), sp); + } + -+ { -+ // UnsafeCopyMemory page error: continue after ucm -+ bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); -+ UnsafeCopyMemoryMark ucmm(this, add_entry, true); -+ copy_memory(aligned, s, d, count, t0, size); -+ } ++ copy_memory(aligned, s, d, count, t0, size); + + if (is_oop) { + __ pop_reg(RegSet::of(d, count), sp); @@ -46965,12 +42329,7 @@ index 00000000000..b3fdd04db1b + __ push_reg(RegSet::of(d, count), sp); + } + -+ { -+ // UnsafeCopyMemory page error: continue after ucm -+ bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); -+ UnsafeCopyMemoryMark ucmm(this, add_entry, true); -+ copy_memory(aligned, s, d, count, t0, -size); -+ } ++ copy_memory(aligned, s, d, count, t0, -size); + + if (is_oop) { + __ pop_reg(RegSet::of(d, count), sp); @@ -47733,7 +43092,7 @@ index 00000000000..b3fdd04db1b + } + + __ BIND(L_failed); -+ __ li(x10, -1); ++ __ mv(x10, -1); + __ leave(); // required for proper stackwalking of RuntimeStub frame + __ ret(); + @@ -48206,50 +43565,6 @@ index 00000000000..b3fdd04db1b + return entry; + } + -+ address generate_method_entry_barrier() { -+ __ align(CodeEntryAlignment); -+ StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier"); -+ -+ Label deoptimize_label; -+ -+ address start = __ pc(); -+ -+ __ set_last_Java_frame(sp, fp, ra, t0); -+ -+ __ enter(); -+ __ add(t1, sp, wordSize); -+ -+ __ sub(sp, sp, 4 * wordSize); -+ -+ __ push_call_clobbered_registers(); -+ -+ __ mv(c_rarg0, t1); -+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier), 1); -+ -+ __ reset_last_Java_frame(true); -+ -+ __ mv(t0, x10); -+ -+ __ pop_call_clobbered_registers(); -+ -+ __ bnez(t0, deoptimize_label); -+ -+ __ leave(); -+ __ ret(); -+ -+ __ BIND(deoptimize_label); -+ -+ __ ld(t0, Address(sp, 0)); -+ __ ld(fp, Address(sp, wordSize)); -+ __ ld(ra, Address(sp, wordSize * 2)); -+ __ ld(t1, Address(sp, wordSize * 3)); -+ -+ __ mv(sp, t0); -+ __ jr(t1); -+ -+ return start; -+ } -+ + // x10 = result + // x11 = str1 + // x12 = cnt1 @@ -48686,111 +44001,6 @@ index 00000000000..b3fdd04db1b + + return entry; + } -+ -+ // Arguments: -+ // -+ // Input: -+ // c_rarg0 - newArr address -+ // c_rarg1 - oldArr address -+ // c_rarg2 - newIdx -+ // c_rarg3 - shiftCount -+ // c_rarg4 - numIter -+ // -+ address generate_bigIntegerLeftShift() { -+ __ align(CodeEntryAlignment); -+ StubCodeMark mark(this, "StubRoutines", "bigIntegerLeftShiftWorker"); -+ address entry = __ pc(); -+ -+ Label loop, exit; -+ -+ Register newArr = c_rarg0; -+ Register oldArr = c_rarg1; -+ Register newIdx = c_rarg2; -+ Register shiftCount = c_rarg3; -+ Register numIter = c_rarg4; -+ -+ Register shiftRevCount = c_rarg5; -+ Register oldArrNext = t1; -+ -+ __ beqz(numIter, exit); -+ __ shadd(newArr, newIdx, newArr, t0, 2); -+ -+ __ li(shiftRevCount, 32); -+ __ sub(shiftRevCount, shiftRevCount, shiftCount); -+ -+ __ bind(loop); -+ __ addi(oldArrNext, oldArr, 4); -+ __ vsetvli(t0, numIter, Assembler::e32, Assembler::m4); -+ __ vle32_v(v0, oldArr); -+ __ vle32_v(v4, oldArrNext); -+ __ vsll_vx(v0, v0, shiftCount); -+ __ vsrl_vx(v4, v4, shiftRevCount); -+ __ vor_vv(v0, v0, v4); -+ __ vse32_v(v0, newArr); -+ __ sub(numIter, numIter, t0); -+ __ shadd(oldArr, t0, oldArr, t1, 2); -+ __ shadd(newArr, t0, newArr, t1, 2); -+ __ bnez(numIter, loop); -+ -+ __ bind(exit); -+ __ ret(); -+ -+ return entry; -+ } -+ -+ // Arguments: -+ // -+ // Input: -+ // c_rarg0 - newArr address -+ // c_rarg1 - oldArr address -+ // c_rarg2 - newIdx -+ // c_rarg3 - shiftCount -+ // c_rarg4 - numIter -+ // -+ address generate_bigIntegerRightShift() { -+ __ align(CodeEntryAlignment); -+ StubCodeMark mark(this, "StubRoutines", "bigIntegerRightShiftWorker"); -+ address entry = __ pc(); -+ -+ Label loop, exit; -+ -+ Register newArr = c_rarg0; -+ Register oldArr = c_rarg1; -+ Register newIdx = c_rarg2; -+ Register shiftCount = c_rarg3; -+ Register numIter = c_rarg4; -+ Register idx = numIter; -+ -+ Register shiftRevCount = c_rarg5; -+ Register oldArrNext = c_rarg6; -+ Register newArrCur = t0; -+ Register oldArrCur = t1; -+ -+ __ beqz(idx, exit); -+ __ shadd(newArr, newIdx, newArr, t0, 2); -+ -+ __ li(shiftRevCount, 32); -+ __ sub(shiftRevCount, shiftRevCount, shiftCount); -+ -+ __ bind(loop); -+ __ vsetvli(t0, idx, Assembler::e32, Assembler::m4); -+ __ sub(idx, idx, t0); -+ __ shadd(oldArrNext, idx, oldArr, t1, 2); -+ __ shadd(newArrCur, idx, newArr, t1, 2); -+ __ addi(oldArrCur, oldArrNext, 4); -+ __ vle32_v(v0, oldArrCur); -+ __ vle32_v(v4, oldArrNext); -+ __ vsrl_vx(v0, v0, shiftCount); -+ __ vsll_vx(v4, v4, shiftRevCount); -+ __ vor_vv(v0, v0, v4); -+ __ vse32_v(v0, newArrCur); -+ __ bnez(idx, loop); -+ -+ __ bind(exit); -+ __ ret(); -+ -+ return entry; -+ } +#endif + +#ifdef COMPILER2 @@ -49070,7 +44280,7 @@ index 00000000000..b3fdd04db1b + ld(Rm, Address(Rm)); + add(Rn, Pn_base, Rn); + ld(Rn, Address(Rn)); -+ li(t0, 1); // set carry flag, i.e. no borrow ++ mv(t0, 1); // set carry flag, i.e. no borrow + align(16); + bind(loop); { + notr(Rn, Rn); @@ -49235,7 +44445,7 @@ index 00000000000..b3fdd04db1b + enter(); + + // Make room. -+ li(Ra, 512); ++ mv(Ra, 512); + bgt(Rlen, Ra, argh); + slli(Ra, Rlen, exact_log2(4 * sizeof(jint))); + sub(Ra, sp, Ra); @@ -49261,7 +44471,7 @@ index 00000000000..b3fdd04db1b + { + ld(Rn, Address(Pn_base)); + mul(Rlo_mn, Rn, inv); -+ li(t0, -1); ++ mv(t0, -1); + Label ok; + beq(Rlo_mn, t0, ok); + stop("broken inverse in Montgomery multiply"); @@ -49357,7 +44567,7 @@ index 00000000000..b3fdd04db1b + enter(); + + // Make room. -+ li(Ra, 512); ++ mv(Ra, 512); + bgt(Rlen, Ra, argh); + slli(Ra, Rlen, exact_log2(4 * sizeof(jint))); + sub(Ra, sp, Ra); @@ -49656,22 +44866,12 @@ index 00000000000..b3fdd04db1b + MontgomeryMultiplyGenerator g(_masm, /*squaring*/true); + StubRoutines::_montgomerySquare = g.generate_square(); + } -+ -+ if (UseRVVForBigIntegerShiftIntrinsics) { -+ StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); -+ StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); -+ } +#endif + + generate_compare_long_strings(); + + generate_string_indexof_stubs(); + -+ BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); -+ if (bs_nm != NULL) { -+ StubRoutines::riscv::_method_entry_barrier = generate_method_entry_barrier(); -+ } -+ + StubRoutines::riscv::set_completed(); + } + @@ -49687,20 +44887,15 @@ index 00000000000..b3fdd04db1b + ~StubGenerator() {} +}; // end class declaration + -+#define UCM_TABLE_MAX_ENTRIES 8 +void StubGenerator_generate(CodeBuffer* code, bool all) { -+ if (UnsafeCopyMemory::_table == NULL) { -+ UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES); -+ } -+ + StubGenerator g(code, all); +} diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp new file mode 100644 -index 00000000000..395a2d338e4 +index 0000000000..9202d9ec4b --- /dev/null +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp -@@ -0,0 +1,58 @@ +@@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -49756,15 +44951,14 @@ index 00000000000..395a2d338e4 +address StubRoutines::riscv::_string_indexof_linear_uu = NULL; +address StubRoutines::riscv::_string_indexof_linear_ul = NULL; +address StubRoutines::riscv::_large_byte_array_inflate = NULL; -+address StubRoutines::riscv::_method_entry_barrier = NULL; + +bool StubRoutines::riscv::_completed = false; diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp new file mode 100644 -index 00000000000..51f07819c33 +index 0000000000..0c9445e18a --- /dev/null +++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp -@@ -0,0 +1,161 @@ +@@ -0,0 +1,155 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -49834,8 +45028,6 @@ index 00000000000..51f07819c33 + static address _string_indexof_linear_ul; + static address _large_byte_array_inflate; + -+ static address _method_entry_barrier; -+ + static bool _completed; + + public: @@ -49912,10 +45104,6 @@ index 00000000000..51f07819c33 + return _large_byte_array_inflate; + } + -+ static address method_entry_barrier() { -+ return _method_entry_barrier; -+ } -+ + static bool complete() { + return _completed; + } @@ -49928,10 +45116,10 @@ index 00000000000..51f07819c33 +#endif // CPU_RISCV_STUBROUTINES_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp new file mode 100644 -index 00000000000..6537b2dbd94 +index 0000000000..34c85e8145 --- /dev/null +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -0,0 +1,1794 @@ +@@ -0,0 +1,1833 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -49985,7 +45173,6 @@ index 00000000000..6537b2dbd94 +#include "runtime/timer.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" -+#include "utilities/powerOfTwo.hpp" +#include + +#ifndef PRODUCT @@ -50475,7 +45662,7 @@ index 00000000000..6537b2dbd94 + address entry = __ pc(); + __ push(state); + __ call_VM(noreg, runtime_entry); -+ __ fence(0xf, 0xf); ++ __ membar(MacroAssembler::AnyAny); + __ dispatch_via(vtos, Interpreter::_normal_table.table_for(vtos)); + return entry; +} @@ -50491,31 +45678,81 @@ index 00000000000..6537b2dbd94 +// +// xmethod: method +// -+void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow) { ++void TemplateInterpreterGenerator::generate_counter_incr( ++ Label* overflow, ++ Label* profile_method, ++ Label* profile_method_continue) { + Label done; + // Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not. -+ int increment = InvocationCounter::count_increment; -+ Label no_mdo; -+ if (ProfileInterpreter) { -+ // Are we profiling? -+ __ ld(x10, Address(xmethod, Method::method_data_offset())); -+ __ beqz(x10, no_mdo); -+ // Increment counter in the MDO -+ const Address mdo_invocation_counter(x10, in_bytes(MethodData::invocation_counter_offset()) + -+ in_bytes(InvocationCounter::counter_offset())); -+ const Address mask(x10, in_bytes(MethodData::invoke_mask_offset())); -+ __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, t0, t1, false, overflow); -+ __ j(done); ++ if (TieredCompilation) { ++ int increment = InvocationCounter::count_increment; ++ Label no_mdo; ++ if (ProfileInterpreter) { ++ // Are we profiling? ++ __ ld(x10, Address(xmethod, Method::method_data_offset())); ++ __ beqz(x10, no_mdo); ++ // Increment counter in the MDO ++ const Address mdo_invocation_counter(x10, in_bytes(MethodData::invocation_counter_offset()) + ++ in_bytes(InvocationCounter::counter_offset())); ++ const Address mask(x10, in_bytes(MethodData::invoke_mask_offset())); ++ __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, t0, t1, false, overflow); ++ __ j(done); ++ } ++ __ bind(no_mdo); ++ // Increment counter in MethodCounters ++ const Address invocation_counter(t1, ++ MethodCounters::invocation_counter_offset() + ++ InvocationCounter::counter_offset()); ++ __ get_method_counters(xmethod, t1, done); ++ const Address mask(t1, in_bytes(MethodCounters::invoke_mask_offset())); ++ __ increment_mask_and_jump(invocation_counter, increment, mask, t0, x11, false, overflow); ++ __ bind(done); ++ } else { // not TieredCompilation ++ const Address backedge_counter(t1, ++ MethodCounters::backedge_counter_offset() + ++ InvocationCounter::counter_offset()); ++ const Address invocation_counter(t1, ++ MethodCounters::invocation_counter_offset() + ++ InvocationCounter::counter_offset()); ++ ++ __ get_method_counters(xmethod, t1, done); ++ ++ if (ProfileInterpreter) { // %%% Merge this into MethodData* ++ __ lwu(x11, Address(t1, MethodCounters::interpreter_invocation_counter_offset())); ++ __ addw(x11, x11, 1); ++ __ sw(x11, Address(t1, MethodCounters::interpreter_invocation_counter_offset())); ++ } ++ // Update standard invocation counters ++ __ lwu(x11, invocation_counter); ++ __ lwu(x10, backedge_counter); ++ ++ __ addw(x11, x11, InvocationCounter::count_increment); ++ __ andi(x10, x10, InvocationCounter::count_mask_value); ++ ++ __ sw(x11, invocation_counter); ++ __ addw(x10, x10, x11); // add both counters ++ ++ // profile_method is non-null only for interpreted method so ++ // profile_method != NULL == !native_call ++ ++ if (ProfileInterpreter && profile_method != NULL) { ++ // Test to see if we should create a method data oop ++ __ ld(t1, Address(xmethod, Method::method_counters_offset())); ++ __ lwu(t1, Address(t1, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); ++ __ blt(x10, t1, *profile_method_continue); ++ ++ // if no method data exists, go to profile_method ++ __ test_method_data_pointer(t1, *profile_method); ++ } ++ ++ { ++ __ ld(t1, Address(xmethod, Method::method_counters_offset())); ++ __ lwu(t1, Address(t1, in_bytes(MethodCounters::interpreter_invocation_limit_offset()))); ++ __ bltu(x10, t1, done); ++ __ j(*overflow); ++ } ++ __ bind(done); + } -+ __ bind(no_mdo); -+ // Increment counter in MethodCounters -+ const Address invocation_counter(t1, -+ MethodCounters::invocation_counter_offset() + -+ InvocationCounter::counter_offset()); -+ __ get_method_counters(xmethod, t1, done); -+ const Address mask(t1, in_bytes(MethodCounters::invoke_mask_offset())); -+ __ increment_mask_and_jump(invocation_counter, increment, mask, t0, x11, false, overflow); -+ __ bind(done); +} + +void TemplateInterpreterGenerator::generate_counter_overflow(Label& do_continue) { @@ -50699,9 +45936,18 @@ index 00000000000..6537b2dbd94 + __ sd(ProfileInterpreter ? t0 : zr, Address(sp, 6 * wordSize)); + + // Get mirror and store it in the frame as GC root for this Method* -+ __ load_mirror(t2, xmethod); -+ __ sd(zr, Address(sp, 5 * wordSize)); -+ __ sd(t2, Address(sp, 4 * wordSize)); ++#if INCLUDE_SHENANDOAHGC ++ if (UseShenandoahGC) { ++ __ load_mirror(x28, xmethod); ++ __ sd(zr, Address(sp, 5 * wordSize)); ++ __ sd(x28, Address(sp, 4 * wordSize)); ++ } else ++#endif ++ { ++ __ load_mirror(t2, xmethod); ++ __ sd(zr, Address(sp, 5 * wordSize)); ++ __ sd(t2, Address(sp, 4 * wordSize)); ++ } + + __ ld(xcpool, Address(xmethod, Method::const_offset())); + __ ld(xcpool, Address(xcpool, ConstMethod::constants_offset())); @@ -50770,7 +46016,7 @@ index 00000000000..6537b2dbd94 + + address entry = __ pc(); + -+ const int referent_offset = java_lang_ref_Reference::referent_offset(); ++ const int referent_offset = java_lang_ref_Reference::referent_offset; + guarantee(referent_offset > 0, "referent offset not initialized"); + + Label slow_path; @@ -50829,42 +46075,16 @@ index 00000000000..6537b2dbd94 +} + +void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { -+ // See more discussion in stackOverflow.hpp. -+ -+ const int shadow_zone_size = checked_cast(StackOverflow::stack_shadow_zone_size()); ++ // Bang each page in the shadow zone. We can't assume it's been done for ++ // an interpreter frame with greater than a page of locals, so each page ++ // needs to be checked. Only true for non-native. ++ const int n_shadow_pages = JavaThread::stack_shadow_zone_size() / os::vm_page_size(); ++ const int start_page = native_call ? n_shadow_pages : 1; + const int page_size = os::vm_page_size(); -+ const int n_shadow_pages = shadow_zone_size / page_size; -+ -+#ifdef ASSERT -+ Label L_good_limit; -+ __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); -+ __ bnez(t0, L_good_limit); -+ __ stop("shadow zone safe limit is not initialized"); -+ __ bind(L_good_limit); -+ -+ Label L_good_watermark; -+ __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -+ __ bnez(t0, L_good_watermark); -+ __ stop("shadow zone growth watermark is not initialized"); -+ __ bind(L_good_watermark); -+#endif -+ -+ Label L_done; -+ -+ __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -+ __ bgtu(sp, t0, L_done); -+ -+ for (int p = 1; p <= n_shadow_pages; p++) { -+ __ bang_stack_with_offset(p * page_size); ++ for (int pages = start_page; pages <= n_shadow_pages ; pages++) { ++ __ sub(t0, sp, pages * page_size); ++ __ sd(zr, Address(t0)); + } -+ -+ // Record the new watermark, but only if the update is above the safe limit. -+ // Otherwise, the next time around the check above would pass the safe limit. -+ __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); -+ __ bleu(sp, t0, L_done); -+ __ sd(sp, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -+ -+ __ bind(L_done); +} + +// Interpreter stub for calling a native method. (asm interpreter) @@ -50929,7 +46149,7 @@ index 00000000000..6537b2dbd94 + // increment invocation count & check for overflow + Label invocation_counter_overflow; + if (inc_counter) { -+ generate_counter_incr(&invocation_counter_overflow); ++ generate_counter_incr(&invocation_counter_overflow, NULL, NULL); + } + + Label continue_after_compile; @@ -51094,16 +46314,7 @@ index 00000000000..6537b2dbd94 + // check for safepoint operation in progress and/or pending suspend requests + { + Label L, Continue; -+ -+ // We need an acquire here to ensure that any subsequent load of the -+ // global SafepointSynchronize::_state flag is ordered after this load -+ // of the thread-local polling word. We don't want this poll to -+ // return false (i.e. not safepointing) and a later poll of the global -+ // SafepointSynchronize::_state spuriously to return true. -+ // -+ // This is to avoid a race when we're in a native->Java transition -+ // racing the code which wakes up from a safepoint. -+ __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); ++ __ safepoint_poll_acquire(L); + __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); + __ beqz(t1, Continue); + __ bind(L); @@ -51159,7 +46370,7 @@ index 00000000000..6537b2dbd94 + { + Label no_reguard; + __ lwu(t0, Address(xthread, in_bytes(JavaThread::stack_guard_state_offset()))); -+ __ addi(t1, zr, (u1)StackOverflow::stack_guard_yellow_reserved_disabled); ++ __ addi(t1, zr, (u1)JavaThread::stack_guard_yellow_reserved_disabled); + __ bne(t0, t1, no_reguard); + + __ pusha(); // only save smashed registers @@ -51350,8 +46561,15 @@ index 00000000000..6537b2dbd94 + + // increment invocation count & check for overflow + Label invocation_counter_overflow; ++ Label profile_method; ++ Label profile_method_continue; + if (inc_counter) { -+ generate_counter_incr(&invocation_counter_overflow); ++ generate_counter_incr(&invocation_counter_overflow, ++ &profile_method, ++ &profile_method_continue); ++ if (ProfileInterpreter) { ++ __ bind(profile_method_continue); ++ } + } + + Label continue_after_compile; @@ -51388,6 +46606,15 @@ index 00000000000..6537b2dbd94 + + // invocation counter overflow + if (inc_counter) { ++ if (ProfileInterpreter) { ++ // We have decided to profile this method in the interpreter ++ __ bind(profile_method); ++ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); ++ __ set_method_data_pointer_for_bcp(); ++ // don't think we need this ++ __ get_method(x11); ++ __ j(profile_method_continue); ++ } + // Handle overflow of counter and compile method + __ bind(invocation_counter_overflow); + generate_counter_overflow(continue_after_compile); @@ -51550,7 +46777,7 @@ index 00000000000..6537b2dbd94 + Label L_done; + + __ lbu(t0, Address(xbcp, 0)); -+ __ li(t1, Bytecodes::_invokestatic); ++ __ mv(t1, Bytecodes::_invokestatic); + __ bne(t1, t0, L_done); + + // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. @@ -51693,7 +46920,7 @@ index 00000000000..6537b2dbd94 + __ push_reg(t0); + __ push_reg(x10); + __ mv(x10, (address) &BytecodeCounter::_counter_value); -+ __ li(t0, 1); ++ __ mv(t0, 1); + __ amoadd_d(zr, x10, t0, Assembler::aqrl); + __ pop_reg(x10); + __ pop_reg(t0); @@ -51728,10 +46955,10 @@ index 00000000000..6537b2dbd94 +#endif // !PRODUCT diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp new file mode 100644 -index 00000000000..d2a301c6e74 +index 0000000000..c22fd3bfcd --- /dev/null +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -0,0 +1,3951 @@ +@@ -0,0 +1,4000 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -51762,7 +46989,6 @@ index 00000000000..d2a301c6e74 +#include "asm/macroAssembler.inline.hpp" +#include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/collectedHeap.hpp" -+#include "gc/shared/tlab_globals.hpp" +#include "interpreter/interp_masm.hpp" +#include "interpreter/interpreter.hpp" +#include "interpreter/interpreterRuntime.hpp" @@ -51778,10 +47004,15 @@ index 00000000000..d2a301c6e74 +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" +#include "runtime/synchronizer.hpp" -+#include "utilities/powerOfTwo.hpp" + +#define __ _masm-> + ++// Platform-dependent initialization ++ ++void TemplateTable::pd_initialize() { ++ // No RISC-V specific initialization ++} ++ +// Address computation: local variables + +static inline Address iaddress(int n) { @@ -51804,15 +47035,12 @@ index 00000000000..d2a301c6e74 + return iaddress(n); +} + -+static inline Address iaddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { -+ assert_cond(_masm != NULL); ++static inline Address iaddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + _masm->shadd(temp, r, xlocals, temp, 3); + return Address(temp, 0); +} + -+static inline Address laddress(Register r, Register temp, -+ InterpreterMacroAssembler* _masm) { -+ assert_cond(_masm != NULL); ++static inline Address laddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + _masm->shadd(temp, r, xlocals, temp, 3); + return Address(temp, Interpreter::local_offset_in_bytes(1));; +} @@ -51821,8 +47049,7 @@ index 00000000000..d2a301c6e74 + return iaddress(r, temp, _masm); +} + -+static inline Address daddress(Register r, Register temp, -+ InterpreterMacroAssembler* _masm) { ++static inline Address daddress(Register r, Register temp, InterpreterMacroAssembler* _masm) { + return laddress(r, temp, _masm); +} + @@ -51868,7 +47095,6 @@ index 00000000000..d2a301c6e74 + Register val, + DecoratorSet decorators) { + assert(val == noreg || val == x10, "parameter is just for looks"); -+ assert_cond(_masm != NULL); + __ store_heap_oop(dst, val, x29, x11, decorators); +} + @@ -51876,7 +47102,6 @@ index 00000000000..d2a301c6e74 + Address src, + Register dst, + DecoratorSet decorators) { -+ assert_cond(_masm != NULL); + __ load_heap_oop(dst, src, x7, x11, decorators); +} + @@ -51970,13 +47195,13 @@ index 00000000000..d2a301c6e74 +void TemplateTable::iconst(int value) +{ + transition(vtos, itos); -+ __ li(x10, value); ++ __ mv(x10, value); +} + +void TemplateTable::lconst(int value) +{ + transition(vtos, ltos); -+ __ li(x10, value); ++ __ mv(x10, value); +} + +void TemplateTable::fconst(int value) @@ -52139,7 +47364,6 @@ index 00000000000..d2a301c6e74 + int32_t offset = 0; + __ movptr_with_offset(rarg, Universe::the_null_sentinel_addr(), offset); + __ ld(tmp, Address(rarg, offset)); -+ __ resolve_oop_handle(tmp); + __ bne(result, tmp, notNull); + __ mv(result, zr); // NULL object reference + __ bind(notNull); @@ -53475,6 +48699,7 @@ index 00000000000..d2a301c6e74 + assert(UseLoopCounter || !UseOnStackReplacement, + "on-stack-replacement requires loop counters"); + Label backedge_counter_overflow; ++ Label profile_method; + Label dispatch; + if (UseLoopCounter) { + // increment backedge counter for backward branches @@ -53499,31 +48724,75 @@ index 00000000000..d2a301c6e74 + __ beqz(t0, dispatch); // No MethodCounters allocated, OutOfMemory + __ bind(has_counters); + -+ Label no_mdo; -+ int increment = InvocationCounter::count_increment; -+ if (ProfileInterpreter) { -+ // Are we profiling? -+ __ ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); -+ __ beqz(x11, no_mdo); -+ // Increment the MDO backedge counter -+ const Address mdo_backedge_counter(x11, in_bytes(MethodData::backedge_counter_offset()) + -+ in_bytes(InvocationCounter::counter_offset())); -+ const Address mask(x11, in_bytes(MethodData::backedge_mask_offset())); -+ __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, -+ x10, t0, false, ++ if (TieredCompilation) { ++ Label no_mdo; ++ int increment = InvocationCounter::count_increment; ++ if (ProfileInterpreter) { ++ // Are we profiling? ++ __ ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); ++ __ beqz(x11, no_mdo); ++ // Increment the MDO backedge counter ++ const Address mdo_backedge_counter(x11, in_bytes(MethodData::backedge_counter_offset()) + ++ in_bytes(InvocationCounter::counter_offset())); ++ const Address mask(x11, in_bytes(MethodData::backedge_mask_offset())); ++ __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, ++ x10, t0, false, ++ UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); ++ __ j(dispatch); ++ } ++ __ bind(no_mdo); ++ // Increment backedge counter in MethodCounters* ++ __ ld(t0, Address(xmethod, Method::method_counters_offset())); ++ const Address mask(t0, in_bytes(MethodCounters::backedge_mask_offset())); ++ __ increment_mask_and_jump(Address(t0, be_offset), increment, mask, ++ x10, t1, false, + UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); -+ __ j(dispatch); ++ } else { // not TieredCompilation ++ // increment counter ++ __ ld(t1, Address(xmethod, Method::method_counters_offset())); ++ __ lwu(x10, Address(t1, be_offset)); // load backedge counter ++ __ addw(t0, x10, InvocationCounter::count_increment); // increment counter ++ __ sw(t0, Address(t1, be_offset)); // store counter ++ ++ __ lwu(x10, Address(t1, inv_offset)); // load invocation counter ++ __ andi(x10, x10, (unsigned)InvocationCounter::count_mask_value, x13); // and the status bits ++ __ addw(x10, x10, t0); // add both counters ++ ++ if (ProfileInterpreter) { ++ // Test to see if we should create a method data oop ++ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); ++ __ blt(x10, t0, dispatch); ++ ++ // if no method data exists, go to profile method ++ __ test_method_data_pointer(x10, profile_method); ++ ++ if (UseOnStackReplacement) { ++ // check for overflow against x11 which is the MDO taken count ++ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); ++ __ bltu(x11, t0, dispatch); // Intel == Assembler::below, lo:unsigned lower ++ ++ // When ProfileInterpreter is on, the backedge_count comes ++ // from the MethodData*, which value does not get reset on ++ // the call to frequency_counter_overflow(). To avoid ++ // excessive calls to the overflow routine while the method is ++ // being compiled, add a second test to make sure the overflow ++ // function is called only once every overflow_frequency. ++ const int overflow_frequency = 1024; ++ __ andi(x11, x11, overflow_frequency - 1); ++ __ beqz(x11, backedge_counter_overflow); ++ ++ } ++ } else { ++ if (UseOnStackReplacement) { ++ // check for overflow against x10, which is the sum of the ++ // counters ++ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); ++ __ bgeu(x10, t0, backedge_counter_overflow); // Intel == Assembler::aboveEqual ++ } ++ } + } -+ __ bind(no_mdo); -+ // Increment backedge counter in MethodCounters* -+ __ ld(t0, Address(xmethod, Method::method_counters_offset())); -+ const Address mask(t0, in_bytes(MethodCounters::backedge_mask_offset())); -+ __ increment_mask_and_jump(Address(t0, be_offset), increment, mask, -+ x10, t1, false, -+ UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); + __ bind(dispatch); + } -+ + // Pre-load the next target bytecode into t0 + __ load_unsigned_byte(t0, Address(xbcp, 0)); + @@ -53532,52 +48801,63 @@ index 00000000000..d2a301c6e74 + // xbcp: target bcp + __ dispatch_only(vtos, /*generate_poll*/true); + -+ if (UseLoopCounter && UseOnStackReplacement) { -+ // invocation counter overflow -+ __ bind(backedge_counter_overflow); -+ __ neg(x12, x12); -+ __ add(x12, x12, xbcp); // branch xbcp -+ // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) -+ __ call_VM(noreg, -+ CAST_FROM_FN_PTR(address, -+ InterpreterRuntime::frequency_counter_overflow), -+ x12); -+ __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode -+ -+ // x10: osr nmethod (osr ok) or NULL (osr not possible) -+ // w11: target bytecode -+ // x12: temporary -+ __ beqz(x10, dispatch); // test result -- no osr if null -+ // nmethod may have been invalidated (VM may block upon call_VM return) -+ __ lbu(x12, Address(x10, nmethod::state_offset())); -+ if (nmethod::in_use != 0) { -+ __ sub(x12, x12, nmethod::in_use); ++ if (UseLoopCounter) { ++ if (ProfileInterpreter && !TieredCompilation) { ++ // Out-of-line code to allocate method data oop. ++ __ bind(profile_method); ++ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); ++ __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode ++ __ set_method_data_pointer_for_bcp(); ++ __ j(dispatch); + } -+ __ bnez(x12, dispatch); + -+ // We have the address of an on stack replacement routine in x10 -+ // We need to prepare to execute the OSR method. First we must -+ // migrate the locals and monitors off of the stack. ++ if (UseOnStackReplacement) { ++ // invocation counter overflow ++ __ bind(backedge_counter_overflow); ++ __ neg(x12, x12); ++ __ add(x12, x12, xbcp); // branch xbcp ++ // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) ++ __ call_VM(noreg, ++ CAST_FROM_FN_PTR(address, ++ InterpreterRuntime::frequency_counter_overflow), ++ x12); ++ __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode + -+ __ mv(x9, x10); // save the nmethod ++ // x10: osr nmethod (osr ok) or NULL (osr not possible) ++ // w11: target bytecode ++ // x12: temporary ++ __ beqz(x10, dispatch); // test result -- no osr if null ++ // nmethod may have been invalidated (VM may block upon call_VM return) ++ __ lbu(x12, Address(x10, nmethod::state_offset())); ++ if (nmethod::in_use != 0) { ++ __ sub(x12, x12, nmethod::in_use); ++ } ++ __ bnez(x12, dispatch); + -+ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); ++ // We have the address of an on stack replacement routine in x10 ++ // We need to prepare to execute the OSR method. First we must ++ // migrate the locals and monitors off of the stack. + -+ // x10 is OSR buffer, move it to expected parameter location -+ __ mv(j_rarg0, x10); ++ __ mv(x9, x10); // save the nmethod + -+ // remove activation -+ // get sender esp -+ __ ld(esp, -+ Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); -+ // remove frame anchor -+ __ leave(); -+ // Ensure compiled code always sees stack at proper alignment -+ __ andi(sp, esp, -16); ++ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); + -+ // and begin the OSR nmethod -+ __ ld(t0, Address(x9, nmethod::osr_entry_point_offset())); -+ __ jr(t0); ++ // x10 is OSR buffer, move it to expected parameter location ++ __ mv(j_rarg0, x10); ++ ++ // remove activation ++ // get sender esp ++ __ ld(esp, ++ Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); ++ // remove frame anchor ++ __ leave(); ++ // Ensure compiled code always sees stack at proper alignment ++ __ andi(sp, esp, -16); ++ ++ // and begin the OSR nmethod ++ __ ld(t0, Address(x9, nmethod::osr_entry_point_offset())); ++ __ jr(t0); ++ } + } +} + @@ -53981,7 +49261,7 @@ index 00000000000..d2a301c6e74 + const Register temp = x9; + assert_different_registers(Rcache, index, temp); + -+ Label resolved, clinit_barrier_slow; ++ Label resolved; + + Bytecodes::Code code = bytecode(); + switch (code) { @@ -53995,10 +49275,6 @@ index 00000000000..d2a301c6e74 + __ mv(t0, (int) code); + __ beq(temp, t0, resolved); + -+ // resolve first time through -+ // Class initialization barrier slow path lands here as well. -+ __ bind(clinit_barrier_slow); -+ + address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache); + __ mv(temp, (int) code); + __ call_VM(noreg, entry, temp); @@ -54008,13 +49284,6 @@ index 00000000000..d2a301c6e74 + // n.b. unlike x86 Rcache is now rcpool plus the indexed offset + // so all clients ofthis method must be modified accordingly + __ bind(resolved); -+ -+ // Class initialization barrier for static methods -+ if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) { -+ __ load_resolved_method_at_index(byte_no, temp, Rcache); -+ __ load_method_holder(temp, temp); -+ __ clinit_barrier(temp, t0, NULL, &clinit_barrier_slow); -+ } +} + +// The Rcache and index registers must be set before call @@ -54921,6 +50190,7 @@ index 00000000000..d2a301c6e74 + // since the parameter_size includes it. + __ push_reg(x9); + __ mv(x9, index); ++ assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); + __ load_resolved_reference_at_index(index, x9); + __ pop_reg(x9); + __ push_reg(index); // push appendix (MethodType, CallSite, etc.) @@ -55104,7 +50374,9 @@ index 00000000000..d2a301c6e74 + __ profile_virtual_call(x13, x30, x9); + + // Get declaring interface class from method, and itable index -+ __ load_method_holder(x10, xmethod); ++ __ ld(x10, Address(xmethod, Method::const_offset())); ++ __ ld(x10, Address(x10, ConstMethod::constants_offset())); ++ __ ld(x10, Address(x10, ConstantPool::pool_holder_offset_in_bytes())); + __ lwu(xmethod, Address(xmethod, Method::itable_index_offset())); + __ subw(xmethod, xmethod, Method::itable_index_max); + __ negw(xmethod, xmethod); @@ -55291,9 +50563,13 @@ index 00000000000..d2a301c6e74 + __ bnez(x13, loop); + } + -+ // initialize object hader only. ++ // initialize object header only. + __ bind(initialize_header); -+ __ mv(t0, (intptr_t)markWord::prototype().value()); ++ if (UseBiasedLocking) { ++ __ ld(t0, Address(x14, Klass::prototype_header_offset())); ++ } else { ++ __ mv(t0, (intptr_t)markOopDesc::prototype()); ++ } + __ sd(t0, Address(x10, oopDesc::mark_offset_in_bytes())); + __ store_klass_gap(x10, zr); // zero klass gap for compressed oops + __ store_klass(x10, x14); // store klass last @@ -55302,7 +50578,7 @@ index 00000000000..d2a301c6e74 + SkipIfEqual skip(_masm, &DTraceAllocProbes, false); + // Trigger dtrace event for fastpath + __ push(atos); // save the return value -+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), x10); ++ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), x10); + __ pop(atos); // restore the return value + } + __ j(done); @@ -55447,7 +50723,7 @@ index 00000000000..d2a301c6e74 + __ j(done); + // Come here on success + __ bind(ok_is_subtype); -+ __ li(x10, 1); ++ __ mv(x10, 1); + + // Collect counts on whether this test sees NULLs a lot or not. + if (ProfileInterpreter) { @@ -55685,7 +50961,7 @@ index 00000000000..d2a301c6e74 +} diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.hpp b/src/hotspot/cpu/riscv/templateTable_riscv.hpp new file mode 100644 -index 00000000000..fcc86108d28 +index 0000000000..fcc86108d2 --- /dev/null +++ b/src/hotspot/cpu/riscv/templateTable_riscv.hpp @@ -0,0 +1,42 @@ @@ -55731,96 +51007,9 @@ index 00000000000..fcc86108d28 +static void index_check(Register array, Register index); + +#endif // CPU_RISCV_TEMPLATETABLE_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp b/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp -new file mode 100644 -index 00000000000..4f50adb05c3 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp -@@ -0,0 +1,33 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "prims/universalNativeInvoker.hpp" -+#include "utilities/debug.hpp" -+ -+address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) { -+ Unimplemented(); -+ return nullptr; -+} -diff --git a/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp b/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp -new file mode 100644 -index 00000000000..ce70da72f2e ---- /dev/null -+++ b/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * 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 "prims/universalUpcallHandler.hpp" -+#include "utilities/debug.hpp" -+ -+address ProgrammableUpcallHandler::generate_upcall_stub(jobject jrec, jobject jabi, jobject jlayout) { -+ Unimplemented(); -+ return nullptr; -+} -+ -+address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject mh, Method* entry, jobject jabi, jobject jconv) { -+ ShouldNotCallThis(); -+ return nullptr; -+} -+ -+bool ProgrammableUpcallHandler::supports_optimized_upcalls() { -+ return false; -+} diff --git a/src/hotspot/cpu/riscv/vmStructs_riscv.hpp b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp new file mode 100644 -index 00000000000..6c89133de02 +index 0000000000..6c89133de0 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmStructs_riscv.hpp @@ -0,0 +1,42 @@ @@ -55866,12 +51055,166 @@ index 00000000000..6c89133de02 +#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) + +#endif // CPU_RISCV_VMSTRUCTS_RISCV_HPP +diff --git a/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp +new file mode 100644 +index 0000000000..6bdce51506 +--- /dev/null ++++ b/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * 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 "memory/allocation.hpp" ++#include "memory/allocation.inline.hpp" ++#include "runtime/os.inline.hpp" ++#include "vm_version_ext_riscv.hpp" ++ ++// VM_Version_Ext statics ++int VM_Version_Ext::_no_of_threads = 0; ++int VM_Version_Ext::_no_of_cores = 0; ++int VM_Version_Ext::_no_of_sockets = 0; ++bool VM_Version_Ext::_initialized = false; ++char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; ++char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; ++ ++void VM_Version_Ext::initialize_cpu_information(void) { ++ // do nothing if cpu info has been initialized ++ if (_initialized) { ++ return; ++ } ++ ++ _no_of_cores = os::processor_count(); ++ _no_of_threads = _no_of_cores; ++ _no_of_sockets = _no_of_cores; ++ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64"); ++ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string); ++ _initialized = true; ++} ++ ++int VM_Version_Ext::number_of_threads(void) { ++ initialize_cpu_information(); ++ return _no_of_threads; ++} ++ ++int VM_Version_Ext::number_of_cores(void) { ++ initialize_cpu_information(); ++ return _no_of_cores; ++} ++ ++int VM_Version_Ext::number_of_sockets(void) { ++ initialize_cpu_information(); ++ return _no_of_sockets; ++} ++ ++const char* VM_Version_Ext::cpu_name(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); ++ return tmp; ++} ++ ++const char* VM_Version_Ext::cpu_description(void) { ++ initialize_cpu_information(); ++ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); ++ if (NULL == tmp) { ++ return NULL; ++ } ++ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); ++ return tmp; ++} +diff --git a/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp +new file mode 100644 +index 0000000000..711e4aeaf6 +--- /dev/null ++++ b/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp +@@ -0,0 +1,55 @@ ++/* ++ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ * ++ */ ++ ++#ifndef CPU_RISCV_VM_VERSION_EXT_RISCV_HPP ++#define CPU_RISCV_VM_VERSION_EXT_RISCV_HPP ++ ++#include "runtime/vm_version.hpp" ++#include "utilities/macros.hpp" ++ ++class VM_Version_Ext : public VM_Version { ++ private: ++ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; ++ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; ++ ++ static int _no_of_threads; ++ static int _no_of_cores; ++ static int _no_of_sockets; ++ static bool _initialized; ++ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; ++ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; ++ ++ public: ++ static int number_of_threads(void); ++ static int number_of_cores(void); ++ static int number_of_sockets(void); ++ ++ static const char* cpu_name(void); ++ static const char* cpu_description(void); ++ static void initialize_cpu_information(void); ++ ++}; ++ ++#endif // CPU_RISCV_VM_VERSION_EXT_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp new file mode 100644 -index 00000000000..768c7633ca6 +index 0000000000..0e8f526bd9 --- /dev/null +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -0,0 +1,230 @@ +@@ -0,0 +1,209 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -55907,11 +51250,19 @@ index 00000000000..768c7633ca6 +#include OS_HEADER_INLINE(os) + +const char* VM_Version::_uarch = ""; ++const char* VM_Version::_vm_mode = ""; +uint32_t VM_Version::_initial_vector_length = 0; + +void VM_Version::initialize() { + get_os_cpu_info(); + ++ // check if satp.mode is supported, currently supports up to SV48(RV64) ++ if (get_satp_mode() > VM_SV48) { ++ vm_exit_during_initialization( ++ err_msg("Unsupported satp mode: %s. Only satp modes up to sv48 are supported for now.", ++ _vm_mode)); ++ } ++ + if (FLAG_IS_DEFAULT(UseFMA)) { + FLAG_SET_DEFAULT(UseFMA, true); + } @@ -55956,11 +51307,6 @@ index 00000000000..768c7633ca6 + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + -+ if (UseSHA3Intrinsics) { -+ warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); -+ FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); -+ } -+ + if (UseCRC32Intrinsics) { + warning("CRC32 intrinsics are not available on this CPU."); + FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); @@ -55971,11 +51317,6 @@ index 00000000000..768c7633ca6 + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + } + -+ if (UseMD5Intrinsics) { -+ warning("MD5 intrinsics are not available on this CPU."); -+ FLAG_SET_DEFAULT(UseMD5Intrinsics, false); -+ } -+ + if (UseRVV) { + if (!(_features & CPU_V)) { + warning("RVV is not supported on this CPU"); @@ -55986,11 +51327,6 @@ index 00000000000..768c7633ca6 + } + } + -+ if (UseRVB && !(_features & CPU_B)) { -+ warning("RVB is not supported on this CPU"); -+ FLAG_SET_DEFAULT(UseRVB, false); -+ } -+ + if (UseRVC && !(_features & CPU_C)) { + warning("RVC is not supported on this CPU"); + FLAG_SET_DEFAULT(UseRVC, false); @@ -56000,7 +51336,7 @@ index 00000000000..768c7633ca6 + FLAG_SET_DEFAULT(AvoidUnalignedAccesses, true); + } + -+ if (UseRVB) { ++ if (UseZbb) { + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_DEFAULT(UsePopCountInstruction, true); + } @@ -56021,6 +51357,10 @@ index 00000000000..768c7633ca6 +#ifdef COMPILER2 + c2_initialize(); +#endif // COMPILER2 ++ ++ UNSUPPORTED_OPTION(CriticalJNINatives); ++ ++ FLAG_SET_DEFAULT(UseMembar, true); +} + +#ifdef COMPILER2 @@ -56041,10 +51381,6 @@ index 00000000000..768c7633ca6 + FLAG_SET_DEFAULT(MaxVectorSize, 0); + } + -+ if (!UseRVV) { -+ FLAG_SET_DEFAULT(UseRVVForBigIntegerShiftIntrinsics, false); -+ } -+ + if (UseRVV) { + if (FLAG_IS_DEFAULT(MaxVectorSize)) { + MaxVectorSize = _initial_vector_length; @@ -56088,26 +51424,12 @@ index 00000000000..768c7633ca6 + } +} +#endif // COMPILER2 -+ -+void VM_Version::initialize_cpu_information(void) { -+ // do nothing if cpu info has been initialized -+ if (_initialized) { -+ return; -+ } -+ -+ _no_of_cores = os::processor_count(); -+ _no_of_threads = _no_of_cores; -+ _no_of_sockets = _no_of_cores; -+ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64"); -+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string); -+ _initialized = true; -+} diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp new file mode 100644 -index 00000000000..8e35530359a +index 0000000000..875511f522 --- /dev/null +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp -@@ -0,0 +1,72 @@ +@@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -56148,18 +51470,27 @@ index 00000000000..8e35530359a + static void c2_initialize(); +#endif // COMPILER2 + ++// VM modes (satp.mode) privileged ISA 1.10 ++enum VM_MODE { ++ VM_MBARE = 0, ++ VM_SV39 = 8, ++ VM_SV48 = 9, ++ VM_SV57 = 10, ++ VM_SV64 = 11 ++}; ++ +protected: + static const char* _uarch; ++ static const char* _vm_mode; + static uint32_t _initial_vector_length; + static void get_os_cpu_info(); + static uint32_t get_current_vector_length(); ++ static VM_MODE get_satp_mode(); + +public: + // Initialization + static void initialize(); + -+ constexpr static bool supports_stack_watermark_barrier() { return true; } -+ + enum Feature_Flag { +#define CPU_FEATURE_FLAGS(decl) \ + decl(I, "i", 8) \ @@ -56168,8 +51499,7 @@ index 00000000000..8e35530359a + decl(F, "f", 5) \ + decl(D, "d", 3) \ + decl(C, "c", 2) \ -+ decl(V, "v", 21) \ -+ decl(B, "b", 1) ++ decl(V, "v", 21) + +#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1 << bit), + CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) @@ -56182,10 +51512,10 @@ index 00000000000..8e35530359a +#endif // CPU_RISCV_VM_VERSION_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.cpp b/src/hotspot/cpu/riscv/vmreg_riscv.cpp new file mode 100644 -index 00000000000..aa7222dc64a +index 0000000000..c4338715f9 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -@@ -0,0 +1,64 @@ +@@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -56228,34 +51558,21 @@ index 00000000000..aa7222dc64a + FloatRegister freg = ::as_FloatRegister(0); + for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { + for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { -+ regName[i++] = reg->name(); ++ regName[i++] = freg->name(); + } + freg = freg->successor(); + } + -+ VectorRegister vreg = ::as_VectorRegister(0); -+ for ( ; i < ConcreteRegisterImpl::max_vpr ; ) { -+ for (int j = 0 ; j < VectorRegisterImpl::max_slots_per_register ; j++) { -+ regName[i++] = reg->name(); -+ } -+ vreg = vreg->successor(); -+ } -+ + for ( ; i < ConcreteRegisterImpl::number_of_registers ; i++) { -+ regName[i] = "NON-GPR-FPR-VPR"; ++ regName[i] = "NON-GPR-FPR"; + } +} -+ -+VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { -+ Unimplemented(); -+ return VMRegImpl::Bad(); -+} diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.hpp b/src/hotspot/cpu/riscv/vmreg_riscv.hpp new file mode 100644 -index 00000000000..9e611b1f671 +index 0000000000..6f613a8f11 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.hpp -@@ -0,0 +1,68 @@ +@@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -56292,10 +51609,6 @@ index 00000000000..9e611b1f671 + return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; +} + -+inline bool is_VectorRegister() { -+ return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_vpr; -+} -+ +inline Register as_Register() { + assert(is_Register(), "must be"); + return ::as_Register(value() / RegisterImpl::max_slots_per_register); @@ -56307,26 +51620,15 @@ index 00000000000..9e611b1f671 + FloatRegisterImpl::max_slots_per_register); +} + -+inline VectorRegister as_VectorRegister() { -+ assert(is_VectorRegister() && ((value() & (VectorRegisterImpl::max_slots_per_register - 1)) == 0), "must be"); -+ return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) / -+ VectorRegisterImpl::max_slots_per_register); -+} -+ +inline bool is_concrete() { + assert(is_reg(), "must be"); -+ if (is_VectorRegister()) { -+ int base = value() - ConcreteRegisterImpl::max_fpr; -+ return (base % VectorRegisterImpl::max_slots_per_register) == 0; -+ } else { -+ return is_even(value()); -+ } ++ return is_even(value()); +} + +#endif // CPU_RISCV_VMREG_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp b/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp new file mode 100644 -index 00000000000..06b70020b4b +index 0000000000..06b70020b4 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmreg_riscv.inline.hpp @@ -0,0 +1,46 @@ @@ -56378,7 +51680,7 @@ index 00000000000..06b70020b4b +#endif // CPU_RISCV_VM_VMREG_RISCV_INLINE_HPP diff --git a/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp new file mode 100644 -index 00000000000..78b81138003 +index 0000000000..448bb09ba7 --- /dev/null +++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp @@ -0,0 +1,260 @@ @@ -56456,7 +51758,7 @@ index 00000000000..78b81138003 +#if (!defined(PRODUCT) && defined(COMPILER2)) + if (CountCompiledCalls) { + __ la(t2, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); -+ __ add_memory_int64(Address(t2), 1); ++ __ increment(Address(t2)); + } +#endif + @@ -56547,7 +51849,7 @@ index 00000000000..78b81138003 +#if (!defined(PRODUCT) && defined(COMPILER2)) + if (CountCompiledCalls) { + __ la(x18, ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr())); -+ __ add_memory_int64(Address(x18), 1); ++ __ increment(Address(x18)); + } +#endif + @@ -56555,7 +51857,7 @@ index 00000000000..78b81138003 + assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0"); + + // Entry arguments: -+ // t2: CompiledICHolder ++ // t1: CompiledICHolder + // j_rarg0: Receiver + + // This stub is called from compiled code which has no callee-saved registers, @@ -56642,59 +51944,11 @@ index 00000000000..78b81138003 + const unsigned int icache_line_size = wordSize; + return icache_line_size; +} -diff --git a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp -index 897be2209e2..ee298f56653 100644 ---- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp -+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp -@@ -1,6 +1,6 @@ - /* -- * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2016, 2019, SAP SE. All rights reserved. -+ * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2016, 2019 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -1447,7 +1447,10 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op - } - - // result = condition ? opr1 : opr2 --void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { -+void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, -+ LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { -+ assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on s390"); -+ - Assembler::branch_condition acond = Assembler::bcondEqual, ncond = Assembler::bcondNotEqual; - switch (condition) { - case lir_cond_equal: acond = Assembler::bcondEqual; ncond = Assembler::bcondNotEqual; break; -diff --git a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp -index cee3140f4f7..82e9de5a06f 100644 ---- a/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp -+++ b/src/hotspot/cpu/x86/c1_LIRAssembler_x86.cpp -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2000, 2022, 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 -@@ -1970,7 +1970,10 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { - } - } - --void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) { -+void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type, -+ LIR_Opr cmp_opr1, LIR_Opr cmp_opr2) { -+ assert(cmp_opr1 == LIR_OprFact::illegalOpr && cmp_opr2 == LIR_OprFact::illegalOpr, "unnecessary cmp oprs on x86"); -+ - Assembler::Condition acond, ncond; - switch (condition) { - case lir_cond_equal: acond = Assembler::equal; ncond = Assembler::notEqual; break; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp -index 3799adf5dd9..6f75e623a9a 100644 +index 2842a11f92..208a374eea 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp -@@ -2845,6 +2845,8 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) { +@@ -2829,6 +2829,8 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) { strncpy(cpuinfo, "IA64", length); #elif defined(PPC) strncpy(cpuinfo, "PPC64", length); @@ -56703,9 +51957,19 @@ index 3799adf5dd9..6f75e623a9a 100644 #elif defined(S390) strncpy(cpuinfo, "S390", length); #elif defined(SPARC) +@@ -4060,7 +4062,8 @@ size_t os::Linux::find_large_page_size() { + IA64_ONLY(256 * M) + PPC_ONLY(4 * M) + S390_ONLY(1 * M) +- SPARC_ONLY(4 * M); ++ SPARC_ONLY(4 * M) ++ RISCV64_ONLY(2 * M); + #endif // ZERO + + FILE *fp = fopen("/proc/meminfo", "r"); diff --git a/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp new file mode 100644 -index 00000000000..f2610af6cdd +index 0000000000..f2610af6cd --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/assembler_linux_riscv.cpp @@ -0,0 +1,26 @@ @@ -56737,10 +52001,10 @@ index 00000000000..f2610af6cdd +// nothing required here diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp new file mode 100644 -index 00000000000..761da5d743e +index 0000000000..4a1ebee8b0 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp -@@ -0,0 +1,134 @@ +@@ -0,0 +1,189 @@ +/* + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -56776,26 +52040,96 @@ index 00000000000..761da5d743e +// Note that memory_order_conservative requires a full barrier after atomic stores. +// See https://patchwork.kernel.org/patch/3575821/ + ++#if defined(__clang_major__) ++#define FULL_COMPILER_ATOMIC_SUPPORT ++#elif (__GNUC__ > 13) || ((__GNUC__ == 13) && (__GNUC_MINOR__ >= 2)) ++#define FULL_COMPILER_ATOMIC_SUPPORT ++#endif ++ ++#define FULL_MEM_BARRIER __sync_synchronize() ++#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE); ++#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE); ++ +template -+struct Atomic::PlatformAdd { -+ template -+ D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { ++struct Atomic::PlatformAdd ++ : Atomic::FetchAndAdd > ++{ ++ template ++ D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const { ++#ifndef FULL_COMPILER_ATOMIC_SUPPORT ++ // If we add add and fetch for sub word and are using older compiler ++ // it must be added here due to not using lib atomic. ++ STATIC_ASSERT(byte_size >= 4); ++#endif ++ + D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; + return res; + } + -+ template -+ D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { -+ return add_and_fetch(dest, add_value, order) - add_value; ++ template ++ D fetch_and_add(I add_value, D volatile* dest, atomic_memory_order order) const { ++ return add_and_fetch(add_value, dest, order) - add_value; + } +}; + ++#ifndef FULL_COMPILER_ATOMIC_SUPPORT ++template<> ++template ++inline T Atomic::PlatformCmpxchg<1>::operator()(T exchange_value, ++ T volatile* dest __attribute__((unused)), ++ T compare_value, ++ atomic_memory_order order) const { ++ STATIC_ASSERT(1 == sizeof(T)); ++ ++ if (order != memory_order_relaxed) { ++ FULL_MEM_BARRIER; ++ } ++ ++ uint32_t volatile* aligned_dst = (uint32_t volatile*)(((uintptr_t)dest) & (~((uintptr_t)0x3))); ++ int shift = 8 * (((uintptr_t)dest) - ((uintptr_t)aligned_dst)); // 0, 8, 16, 24 ++ ++ uint64_t mask = 0xfful << shift; // 0x00000000..FF.. ++ uint64_t remask = ~mask; // 0xFFFFFFFF..00.. ++ ++ uint64_t w_cv = ((uint64_t)(unsigned char)compare_value) << shift; // widen to 64-bit 0x00000000..CC.. ++ uint64_t w_ev = ((uint64_t)(unsigned char)exchange_value) << shift; // widen to 64-bit 0x00000000..EE.. ++ ++ uint64_t old_value; ++ uint64_t rc_temp; ++ ++ __asm__ __volatile__ ( ++ "1: lr.w %0, %2 \n\t" ++ " and %1, %0, %5 \n\t" // ignore unrelated bytes and widen to 64-bit 0x00000000..XX.. ++ " bne %1, %3, 2f \n\t" // compare 64-bit w_cv ++ " and %1, %0, %6 \n\t" // remove old byte ++ " or %1, %1, %4 \n\t" // add new byte ++ " sc.w %1, %1, %2 \n\t" // store new word ++ " bnez %1, 1b \n\t" ++ "2: \n\t" ++ : /*%0*/"=&r" (old_value), /*%1*/"=&r" (rc_temp), /*%2*/"+A" (*aligned_dst) ++ : /*%3*/"r" (w_cv), /*%4*/"r" (w_ev), /*%5*/"r" (mask), /*%6*/"r" (remask) ++ : "memory" ); ++ ++ if (order != memory_order_relaxed) { ++ FULL_MEM_BARRIER; ++ } ++ ++ return (T)((old_value & mask) >> shift); ++} ++#endif ++ +template +template -+inline T Atomic::PlatformXchg::operator()(T volatile* dest, -+ T exchange_value, ++inline T Atomic::PlatformXchg::operator()(T exchange_value, ++ T volatile* dest, + atomic_memory_order order) const { ++#ifndef FULL_COMPILER_ATOMIC_SUPPORT ++ // If we add xchg for sub word and are using older compiler ++ // it must be added here due to not using lib atomic. ++ STATIC_ASSERT(byte_size >= 4); ++#endif ++ + STATIC_ASSERT(byte_size == sizeof(T)); + T res = __atomic_exchange_n(dest, exchange_value, __ATOMIC_RELEASE); + FULL_MEM_BARRIER; @@ -56805,10 +52139,15 @@ index 00000000000..761da5d743e +// __attribute__((unused)) on dest is to get rid of spurious GCC warnings. +template +template -+inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attribute__((unused)), ++inline T Atomic::PlatformCmpxchg::operator()(T exchange_value, ++ T volatile* dest __attribute__((unused)), + T compare_value, -+ T exchange_value, + atomic_memory_order order) const { ++ ++#ifndef FULL_COMPILER_ATOMIC_SUPPORT ++ STATIC_ASSERT(byte_size >= 4); ++#endif ++ + STATIC_ASSERT(byte_size == sizeof(T)); + T value = compare_value; + if (order != memory_order_relaxed) { @@ -56826,9 +52165,9 @@ index 00000000000..761da5d743e + +template<> +template -+inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)), ++inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, ++ T volatile* dest __attribute__((unused)), + T compare_value, -+ T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + if (order != memory_order_relaxed) { @@ -56853,31 +52192,11 @@ index 00000000000..761da5d743e + return rv; +} + -+template -+struct Atomic::PlatformOrderedLoad -+{ -+ template -+ T operator()(const volatile T* p) const { T data; __atomic_load(const_cast(p), &data, __ATOMIC_ACQUIRE); return data; } -+}; -+ -+template -+struct Atomic::PlatformOrderedStore -+{ -+ template -+ void operator()(volatile T* p, T v) const { __atomic_store(const_cast(p), &v, __ATOMIC_RELEASE); } -+}; -+ -+template -+struct Atomic::PlatformOrderedStore -+{ -+ template -+ void operator()(volatile T* p, T v) const { release_store(p, v); OrderAccess::fence(); } -+}; -+ ++#undef FULL_COMPILER_ATOMIC_SUPPORT +#endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp new file mode 100644 -index 00000000000..28868c76406 +index 0000000000..28868c7640 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/bytes_linux_riscv.hpp @@ -0,0 +1,45 @@ @@ -56926,12 +52245,12 @@ index 00000000000..28868c76406 +} + +#endif // OS_CPU_LINUX_RISCV_BYTES_LINUX_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp +diff --git a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp new file mode 100644 -index 00000000000..147cfdf3c10 +index 0000000000..bdf36d6b4c --- /dev/null -+++ b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp -@@ -0,0 +1,31 @@ ++++ b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp +@@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -56957,63 +52276,108 @@ index 00000000000..147cfdf3c10 + * + */ + -+#ifndef OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP -+#define OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP ++#ifndef OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP ++#define OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP + -+// Empty for build system ++static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { ++ (void)memmove(to, from, count * HeapWordSize); ++} + -+#endif // OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp -new file mode 100644 -index 00000000000..1aa58f27871 ---- /dev/null -+++ b/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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. -+ * -+ */ ++static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { ++ switch (count) { ++ case 8: to[7] = from[7]; // fall through ++ case 7: to[6] = from[6]; // fall through ++ case 6: to[5] = from[5]; // fall through ++ case 5: to[4] = from[4]; // fall through ++ case 4: to[3] = from[3]; // fall through ++ case 3: to[2] = from[2]; // fall through ++ case 2: to[1] = from[1]; // fall through ++ case 1: to[0] = from[0]; // fall through ++ case 0: break; ++ default: ++ memcpy(to, from, count * HeapWordSize); ++ break; ++ } ++} + -+#ifndef OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP -+#define OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP ++static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { ++ switch (count) { ++ case 8: to[7] = from[7]; ++ case 7: to[6] = from[6]; ++ case 6: to[5] = from[5]; ++ case 5: to[4] = from[4]; ++ case 4: to[3] = from[3]; ++ case 3: to[2] = from[2]; ++ case 2: to[1] = from[1]; ++ case 1: to[0] = from[0]; ++ case 0: break; ++ default: ++ while (count-- > 0) { ++ *to++ = *from++; ++ } ++ break; ++ } ++} + -+#include ++static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { ++ pd_conjoint_words(from, to, count); ++} + -+// -+// Support for building on older Linux systems -+// ++static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { ++ pd_disjoint_words(from, to, count); ++} + -+#ifndef SYS_memfd_create -+#define SYS_memfd_create 279 -+#endif -+#ifndef SYS_fallocate -+#define SYS_fallocate 47 -+#endif ++static void pd_conjoint_bytes(const void* from, void* to, size_t count) { ++ (void)memmove(to, from, count); ++} + -+#endif // OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP ++static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { ++ pd_conjoint_bytes(from, to, count); ++} ++ ++static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { ++ _Copy_conjoint_jshorts_atomic(from, to, count); ++} ++ ++static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { ++ _Copy_conjoint_jints_atomic(from, to, count); ++} ++ ++static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { ++ _Copy_conjoint_jlongs_atomic(from, to, count); ++} ++ ++static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { ++ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size."); ++ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); ++} ++ ++static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { ++ _Copy_arrayof_conjoint_bytes(from, to, count); ++} ++ ++static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { ++ _Copy_arrayof_conjoint_jshorts(from, to, count); ++} ++ ++static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { ++ _Copy_arrayof_conjoint_jints(from, to, count); ++} ++ ++static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { ++ _Copy_arrayof_conjoint_jlongs(from, to, count); ++} ++ ++static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { ++ assert(!UseCompressedOops, "foo!"); ++ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); ++ _Copy_arrayof_conjoint_jlongs(from, to, count); ++} ++ ++#endif // OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp new file mode 100644 -index 00000000000..297414bfcd5 +index 0000000000..297414bfcd --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/globals_linux_riscv.hpp @@ -0,0 +1,43 @@ @@ -57062,10 +52426,10 @@ index 00000000000..297414bfcd5 +#endif // OS_CPU_LINUX_RISCV_VM_GLOBALS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp new file mode 100644 -index 00000000000..1c33dc1e87f +index 0000000000..5b5d35553f --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp -@@ -0,0 +1,63 @@ +@@ -0,0 +1,74 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -57105,10 +52469,6 @@ index 00000000000..1c33dc1e87f +inline void OrderAccess::loadstore() { acquire(); } +inline void OrderAccess::storeload() { fence(); } + -+#define FULL_MEM_BARRIER __sync_synchronize() -+#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE); -+#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE); -+ +inline void OrderAccess::acquire() { + READ_MEM_BARRIER; +} @@ -57121,20 +52481,35 @@ index 00000000000..1c33dc1e87f + FULL_MEM_BARRIER; +} + -+inline void OrderAccess::cross_modify_fence_impl() { -+ asm volatile("fence.i" : : : "memory"); -+ if (UseConservativeFence) { -+ asm volatile("fence ir, ir" : : : "memory"); -+ } -+} ++ ++template ++struct OrderAccess::PlatformOrderedLoad ++{ ++ template ++ T operator()(const volatile T* p) const { T data; __atomic_load(const_cast(p), &data, __ATOMIC_ACQUIRE); return data; } ++}; ++ ++template ++struct OrderAccess::PlatformOrderedStore ++{ ++ template ++ void operator()(T v, volatile T* p) const { __atomic_store(const_cast(p), &v, __ATOMIC_RELEASE); } ++}; ++ ++template ++struct OrderAccess::PlatformOrderedStore ++{ ++ template ++ void operator()(T v, volatile T* p) const { release_store(p, v); OrderAccess::fence(); } ++}; + +#endif // OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp new file mode 100644 -index 00000000000..1f46bbab0a2 +index 0000000000..8b772892b4 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -@@ -0,0 +1,466 @@ +@@ -0,0 +1,624 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -57174,6 +52549,7 @@ index 00000000000..1f46bbab0a2 +#include "prims/jniFastGetField.hpp" +#include "prims/jvm_misc.hpp" +#include "runtime/arguments.hpp" ++#include "runtime/extendedPC.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/java.hpp" @@ -57185,7 +52561,6 @@ index 00000000000..1f46bbab0a2 +#include "runtime/stubRoutines.hpp" +#include "runtime/thread.inline.hpp" +#include "runtime/timer.hpp" -+#include "signals_posix.hpp" +#include "utilities/debug.hpp" +#include "utilities/events.hpp" +#include "utilities/vmError.hpp" @@ -57223,11 +52598,11 @@ index 00000000000..1f46bbab0a2 + return (char*) -1; +} + -+address os::Posix::ucontext_get_pc(const ucontext_t * uc) { ++address os::Linux::ucontext_get_pc(const ucontext_t * uc) { + return (address)uc->uc_mcontext.__gregs[REG_PC]; +} + -+void os::Posix::ucontext_set_pc(ucontext_t * uc, address pc) { ++void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { + uc->uc_mcontext.__gregs[REG_PC] = (intptr_t)pc; +} + @@ -57239,13 +52614,29 @@ index 00000000000..1f46bbab0a2 + return (intptr_t*)uc->uc_mcontext.__gregs[REG_FP]; +} + -+address os::fetch_frame_from_context(const void* ucVoid, -+ intptr_t** ret_sp, intptr_t** ret_fp) { -+ address epc; ++// For Forte Analyzer AsyncGetCallTrace profiling support - thread ++// is currently interrupted by SIGPROF. ++// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal ++// frames. Currently we don't do that on Linux, so it's the same as ++// os::fetch_frame_from_context(). ++ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, ++ const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { ++ ++ assert(thread != NULL, "just checking"); ++ assert(ret_sp != NULL, "just checking"); ++ assert(ret_fp != NULL, "just checking"); ++ ++ return os::fetch_frame_from_context(uc, ret_sp, ret_fp); ++} ++ ++ExtendedPC os::fetch_frame_from_context(const void* ucVoid, ++ intptr_t** ret_sp, intptr_t** ret_fp) { ++ ++ ExtendedPC epc; + const ucontext_t* uc = (const ucontext_t*)ucVoid; + + if (uc != NULL) { -+ epc = os::Posix::ucontext_get_pc(uc); ++ epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); + if (ret_sp != NULL) { + *ret_sp = os::Linux::ucontext_get_sp(uc); + } @@ -57253,7 +52644,8 @@ index 00000000000..1f46bbab0a2 + *ret_fp = os::Linux::ucontext_get_fp(uc); + } + } else { -+ epc = NULL; ++ // construct empty ExtendedPC for return value checking ++ epc = ExtendedPC(NULL); + if (ret_sp != NULL) { + *ret_sp = (intptr_t *)NULL; + } @@ -57265,23 +52657,51 @@ index 00000000000..1f46bbab0a2 + return epc; +} + -+frame os::fetch_compiled_frame_from_context(const void* ucVoid) { -+ const ucontext_t* uc = (const ucontext_t*)ucVoid; -+ // In compiled code, the stack banging is performed before RA -+ // has been saved in the frame. RA is live, and SP and FP -+ // belong to the caller. -+ intptr_t* frame_fp = os::Linux::ucontext_get_fp(uc); -+ intptr_t* frame_sp = os::Linux::ucontext_get_sp(uc); -+ address frame_pc = (address)(uc->uc_mcontext.__gregs[REG_LR] -+ - NativeInstruction::instruction_size); -+ return frame(frame_sp, frame_fp, frame_pc); -+} -+ +frame os::fetch_frame_from_context(const void* ucVoid) { + intptr_t* frame_sp = NULL; + intptr_t* frame_fp = NULL; -+ address epc = fetch_frame_from_context(ucVoid, &frame_sp, &frame_fp); -+ return frame(frame_sp, frame_fp, epc); ++ ExtendedPC epc = fetch_frame_from_context(ucVoid, &frame_sp, &frame_fp); ++ return frame(frame_sp, frame_fp, epc.pc()); ++} ++ ++bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { ++ address pc = (address) os::Linux::ucontext_get_pc(uc); ++ if (Interpreter::contains(pc)) { ++ // interpreter performs stack banging after the fixed frame header has ++ // been generated while the compilers perform it before. To maintain ++ // semantic consistency between interpreted and compiled frames, the ++ // method returns the Java sender of the current frame. ++ *fr = os::fetch_frame_from_context(uc); ++ if (!fr->is_first_java_frame()) { ++ assert(fr->safe_for_sender(thread), "Safety check"); ++ *fr = fr->java_sender(); ++ } ++ } else { ++ // more complex code with compiled code ++ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); ++ CodeBlob* cb = CodeCache::find_blob(pc); ++ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { ++ // Not sure where the pc points to, fallback to default ++ // stack overflow handling ++ return false; ++ } else { ++ // In compiled code, the stack banging is performed before RA ++ // has been saved in the frame. RA is live, and SP and FP ++ // belong to the caller. ++ intptr_t* fp = os::Linux::ucontext_get_fp(uc); ++ intptr_t* sp = os::Linux::ucontext_get_sp(uc); ++ address pc = (address)(uc->uc_mcontext.__gregs[REG_LR] ++ - NativeInstruction::instruction_size); ++ *fr = frame(sp, fp, pc); ++ if (!fr->is_java_frame()) { ++ assert(fr->safe_for_sender(thread), "Safety check"); ++ assert(!fr->is_first_frame(), "Safety check"); ++ *fr = fr->java_sender(); ++ } ++ } ++ } ++ assert(fr->is_java_frame(), "Safety check"); ++ return true; +} + +// By default, gcc always saves frame pointer rfp on this stack. This @@ -57309,31 +52729,138 @@ index 00000000000..1f46bbab0a2 +} + +// Utility functions -+bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, -+ ucontext_t* uc, JavaThread* thread) { ++extern "C" JNIEXPORT int ++JVM_handle_linux_signal(int sig, ++ siginfo_t* info, ++ void* ucVoid, ++ int abort_if_unrecognized) { ++ ucontext_t* uc = (ucontext_t*) ucVoid; ++ ++ Thread* t = Thread::current_or_null_safe(); ++ ++ // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away ++ // (no destructors can be run) ++ os::ThreadCrashProtection::check_crash_protection(sig, t); ++ ++ SignalHandlerMark shm(t); ++ ++ // Note: it's not uncommon that JNI code uses signal/sigset to install ++ // then restore certain signal handler (e.g. to temporarily block SIGPIPE, ++ // or have a SIGILL handler when detecting CPU type). When that happens, ++ // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To ++ // avoid unnecessary crash when libjsig is not preloaded, try handle signals ++ // that do not require siginfo/ucontext first. ++ ++ if (sig == SIGPIPE || sig == SIGXFSZ) { ++ // allow chained handler to go first ++ if (os::Linux::chained_handler(sig, info, ucVoid)) { ++ return true; ++ } else { ++ // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 ++ return true; ++ } ++ } ++ ++#ifdef CAN_SHOW_REGISTERS_ON_ASSERT ++ if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) { ++ if (handle_assert_poison_fault(ucVoid, info->si_addr)) { ++ return 1; ++ } ++ } ++#endif ++ ++ JavaThread* thread = NULL; ++ VMThread* vmthread = NULL; ++ if (os::Linux::signal_handlers_are_installed) { ++ if (t != NULL ){ ++ if(t->is_Java_thread()) { ++ thread = (JavaThread *) t; ++ } ++ else if(t->is_VM_thread()){ ++ vmthread = (VMThread *)t; ++ } ++ } ++ } ++ ++ // Handle SafeFetch faults ++ if ((sig == SIGSEGV || sig == SIGBUS) && uc != NULL) { ++ address const pc = (address) os::Linux::ucontext_get_pc(uc); ++ if (pc && StubRoutines::is_safefetch_fault(pc)) { ++ os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); ++ return 1; ++ } ++ } + + // decide if this trap can be handled by a stub + address stub = NULL; + -+ address pc = NULL; ++ address pc = NULL; + + //%note os_trap_1 + if (info != NULL && uc != NULL && thread != NULL) { -+ pc = (address) os::Posix::ucontext_get_pc(uc); -+ -+ address addr = (address) info->si_addr; -+ -+ // Make sure the high order byte is sign extended, as it may be masked away by the hardware. -+ if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) { -+ addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56)); -+ } ++ pc = (address) os::Linux::ucontext_get_pc(uc); + + // Handle ALL stack overflow variations here + if (sig == SIGSEGV) { ++ address addr = (address) info->si_addr; ++ + // check if fault address is within thread stack -+ if (thread->is_in_full_stack(addr)) { -+ if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) { -+ return true; // continue ++ if (thread->on_local_stack(addr)) { ++ // stack overflow ++ if (thread->in_stack_yellow_reserved_zone(addr)) { ++ if (thread->thread_state() == _thread_in_Java) { ++ if (thread->in_stack_reserved_zone(addr)) { ++ frame fr; ++ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) { ++ assert(fr.is_java_frame(), "Must be a Java frame"); ++ frame activation = ++ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); ++ if (activation.sp() != NULL) { ++ thread->disable_stack_reserved_zone(); ++ if (activation.is_interpreted_frame()) { ++ thread->set_reserved_stack_activation((address)( ++ activation.fp() + frame::interpreter_frame_initial_sp_offset)); ++ } else { ++ thread->set_reserved_stack_activation((address)activation.unextended_sp()); ++ } ++ return 1; ++ } ++ } ++ } ++ // Throw a stack overflow exception. Guard pages will be reenabled ++ // while unwinding the stack. ++ thread->disable_stack_yellow_reserved_zone(); ++ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); ++ } else { ++ // Thread was in the vm or native code. Return and try to finish. ++ thread->disable_stack_yellow_reserved_zone(); ++ return 1; ++ } ++ } else if (thread->in_stack_red_zone(addr)) { ++ // Fatal red zone violation. Disable the guard pages and fall through ++ // to handle_unexpected_exception way down below. ++ thread->disable_stack_red_zone(); ++ tty->print_raw_cr("An irrecoverable stack overflow has occurred."); ++ ++ // This is a likely cause, but hard to verify. Let's just print ++ // it as a hint. ++ tty->print_raw_cr("Please check if any of your loaded .so files has " ++ "enabled executable stack (see man page execstack(8))"); ++ } else { ++ // Accessing stack address below sp may cause SEGV if current ++ // thread has MAP_GROWSDOWN stack. This should only happen when ++ // current thread was created by user code with MAP_GROWSDOWN flag ++ // and then attached to VM. See notes in os_linux.cpp. ++ if (thread->osthread()->expanding_stack() == 0) { ++ thread->osthread()->set_expanding_stack(); ++ if (os::Linux::manually_expand_stack(thread, addr)) { ++ thread->osthread()->clear_expanding_stack(); ++ return 1; ++ } ++ thread->osthread()->clear_expanding_stack(); ++ } else { ++ fatal("recursive segv. expanding stack."); ++ } + } + } + } @@ -57349,7 +52876,7 @@ index 00000000000..1f46bbab0a2 + tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); + } + stub = SharedRuntime::get_handle_wrong_method_stub(); -+ } else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { ++ } else if (sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) { + stub = SharedRuntime::get_poll_stub(pc); + } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { + // BugId 4454115: A read from a MappedByteBuffer can fault @@ -57357,34 +52884,12 @@ index 00000000000..1f46bbab0a2 + // Do not crash the VM in such a case. + CodeBlob* cb = CodeCache::find_blob_unsafe(pc); + CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; -+ bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc)); -+ if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) { ++ if (nm != NULL && nm->has_unsafe_access()) { + address next_pc = pc + NativeCall::instruction_size; -+ if (is_unsafe_arraycopy) { -+ next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); -+ } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } -+ } else if (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) { -+ // Pull a pointer to the error message out of the instruction -+ // stream. -+ const uint64_t *detail_msg_ptr -+ = (uint64_t*)(pc + NativeInstruction::instruction_size); -+ const char *detail_msg = (const char *)*detail_msg_ptr; -+ const char *msg = "stop"; -+ if (TraceTraps) { -+ tty->print_cr("trap: %s: (SIGILL)", msg); -+ } -+ -+ // End life with a fatal error, message and detail message and the context. -+ // Note: no need to do any post-processing here (e.g. signal chaining) -+ va_list va_dummy; -+ VMError::report_and_die(thread, uc, NULL, 0, msg, detail_msg, va_dummy); -+ va_end(va_dummy); -+ -+ ShouldNotReachHere(); + } else if (sig == SIGFPE && -+ (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { ++ (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { + stub = + SharedRuntime:: + continuation_for_implicit_exception(thread, @@ -57392,42 +52897,70 @@ index 00000000000..1f46bbab0a2 + SharedRuntime:: + IMPLICIT_DIVIDE_BY_ZERO); + } else if (sig == SIGSEGV && -+ MacroAssembler::uses_implicit_null_check((void*)addr)) { ++ !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { + // Determination of interpreter/vtable stub/compiled code null exception + stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); + } -+ } else if ((thread->thread_state() == _thread_in_vm || -+ thread->thread_state() == _thread_in_native) && -+ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ -+ thread->doing_unsafe_access()) { ++ } else if (thread->thread_state() == _thread_in_vm && ++ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ ++ thread->doing_unsafe_access()) { + address next_pc = pc + NativeCall::instruction_size; -+ if (UnsafeCopyMemory::contains_pc(pc)) { -+ next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); -+ } + stub = SharedRuntime::handle_unsafe_access(thread, next_pc); + } + + // jni_fast_GetField can trap at certain pc's if a GC kicks in + // and the heap gets shrunk before the field access. + if ((sig == SIGSEGV) || (sig == SIGBUS)) { -+ address addr_slow = JNI_FastGetField::find_slowcase_pc(pc); -+ if (addr_slow != (address)-1) { -+ stub = addr_slow; ++ address addr = JNI_FastGetField::find_slowcase_pc(pc); ++ if (addr != (address)-1) { ++ stub = addr; + } + } ++ ++ // Check to see if we caught the safepoint code in the ++ // process of write protecting the memory serialization page. ++ // It write enables the page immediately after protecting it ++ // so we can just return to retry the write. ++ if ((sig == SIGSEGV) && ++ os::is_memory_serialize_page(thread, (address) info->si_addr)) { ++ // Block current thread until the memory serialize page permission restored. ++ os::block_on_serialize_page_trap(); ++ return true; ++ } + } + + if (stub != NULL) { + // save all thread context in case we need to restore it -+ if (thread != NULL) { -+ thread->set_saved_exception_pc(pc); -+ } ++ if (thread != NULL) thread->set_saved_exception_pc(pc); + -+ os::Posix::ucontext_set_pc(uc, stub); ++ os::Linux::ucontext_set_pc(uc, stub); + return true; + } + -+ return false; // Mute compiler ++ // signal-chaining ++ if (os::Linux::chained_handler(sig, info, ucVoid)) { ++ return true; ++ } ++ ++ if (!abort_if_unrecognized) { ++ // caller wants another chance, so give it to him ++ return false; ++ } ++ ++ if (pc == NULL && uc != NULL) { ++ pc = os::Linux::ucontext_get_pc(uc); ++ } ++ ++ // unmask current signal ++ sigset_t newset; ++ sigemptyset(&newset); ++ sigaddset(&newset, sig); ++ sigprocmask(SIG_UNBLOCK, &newset, NULL); ++ ++ VMError::report_and_die(t, sig, pc, info, ucVoid); ++ ++ ShouldNotReachHere(); ++ return true; // Mute compiler +} + +void os::Linux::init_thread_fpu_state(void) { @@ -57490,7 +53023,7 @@ index 00000000000..1f46bbab0a2 + // Note: it may be unsafe to inspect memory near pc. For example, pc may + // point to garbage if entry point in an nmethod is corrupted. Leave + // this at the end, and hope for the best. -+ address pc = os::Posix::ucontext_get_pc(uc); ++ address pc = os::Linux::ucontext_get_pc(uc); + print_instructions(st, pc, sizeof(char)); + st->cr(); +} @@ -57603,10 +53136,10 @@ index 00000000000..1f46bbab0a2 +}; diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp new file mode 100644 -index 00000000000..6d415630661 +index 0000000000..f3e3a73bc5 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.hpp -@@ -0,0 +1,59 @@ +@@ -0,0 +1,40 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -57646,29 +53179,10 @@ index 00000000000..6d415630661 + *(jlong *) dst = *(const jlong *) src; + } + -+ // SYSCALL_RISCV_FLUSH_ICACHE is used to flush instruction cache. The "fence.i" instruction -+ // only work on the current hart, so kernel provides the icache flush syscall to flush icache -+ // on each hart. You can pass a flag to determine a global or local icache flush. -+ static void icache_flush(long int start, long int end) -+ { -+ const int SYSCALL_RISCV_FLUSH_ICACHE = 259; -+ register long int __a7 asm ("a7") = SYSCALL_RISCV_FLUSH_ICACHE; -+ register long int __a0 asm ("a0") = start; -+ register long int __a1 asm ("a1") = end; -+ // the flush can be applied to either all threads or only the current. -+ // 0 means a global icache flush, and the icache flush will be applied -+ // to other harts concurrently executing. -+ register long int __a2 asm ("a2") = 0; -+ __asm__ volatile ("ecall\n\t" -+ : "+r" (__a0) -+ : "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a7) -+ : "memory"); -+ } -+ +#endif // OS_CPU_LINUX_RISCV_VM_OS_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp new file mode 100644 -index 00000000000..a6432c84ec7 +index 0000000000..2bd48e09c3 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp @@ -0,0 +1,38 @@ @@ -57703,19 +53217,147 @@ index 00000000000..a6432c84ec7 +#include "runtime/prefetch.hpp" + + -+inline void Prefetch::read (const void *loc, intx interval) { ++inline void Prefetch::read (void *loc, intx interval) { +} + +inline void Prefetch::write(void *loc, intx interval) { +} + +#endif // OS_CPU_LINUX_RISCV_VM_PREFETCH_LINUX_RISCV_INLINE_HPP +diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.cpp +new file mode 100644 +index 0000000000..ffcd819487 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.cpp +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2023, Rivos Inc. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * 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 "logging/log.hpp" ++#include "riscv_flush_icache.hpp" ++#include "runtime/os.hpp" ++#include "runtime/vm_version.hpp" ++#include "utilities/debug.hpp" ++ ++#include ++#include ++ ++#define check_with_errno(check_type, cond, msg) \ ++ do { \ ++ int err = errno; \ ++ check_type(cond, "%s; error='%s' (errno=%s)", msg, os::strerror(err), \ ++ os::errno_name(err)); \ ++} while (false) ++ ++#define assert_with_errno(cond, msg) check_with_errno(assert, cond, msg) ++#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg) ++ ++#ifndef NR_riscv_flush_icache ++#ifndef NR_arch_specific_syscall ++#define NR_arch_specific_syscall 244 ++#endif ++#define NR_riscv_flush_icache (NR_arch_specific_syscall + 15) ++#endif ++ ++#define SYS_RISCV_FLUSH_ICACHE_LOCAL 1UL ++#define SYS_RISCV_FLUSH_ICACHE_ALL 0UL ++ ++static long sys_flush_icache(uintptr_t start, uintptr_t end , uintptr_t flags) { ++ return syscall(NR_riscv_flush_icache, start, end, flags); ++} ++ ++bool RiscvFlushIcache::test() { ++ ATTRIBUTE_ALIGNED(64) char memory[64]; ++ long ret = sys_flush_icache((uintptr_t)&memory[0], ++ (uintptr_t)&memory[sizeof(memory) - 1], ++ SYS_RISCV_FLUSH_ICACHE_ALL); ++ if (ret == 0) { ++ return true; ++ } ++ int err = errno; \ ++ log_error(os)("Syscall: RISCV_FLUSH_ICACHE not available; error='%s' (errno=%s)", ++ os::strerror(err), os::errno_name(err)); ++ return false; ++} ++ ++void RiscvFlushIcache::flush(uintptr_t start, uintptr_t end) { ++ long ret = sys_flush_icache(start, end, SYS_RISCV_FLUSH_ICACHE_ALL); ++ guarantee_with_errno(ret == 0, "riscv_flush_icache failed"); ++} +diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.hpp b/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.hpp +new file mode 100644 +index 0000000000..f4e7263b39 +--- /dev/null ++++ b/src/hotspot/os_cpu/linux_riscv/riscv_flush_icache.hpp +@@ -0,0 +1,39 @@ ++/* ++ * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2023, Rivos Inc. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ * ++ */ ++ ++#ifndef OS_LINUX_RISCV_FLUSH_ICACHE_LINUX_HPP ++#define OS_LINUX_RISCV_FLUSH_ICACHE_LINUX_HPP ++ ++#include "memory/allocation.hpp" ++#include "runtime/vm_version.hpp" ++#include "utilities/growableArray.hpp" ++ ++class RiscvFlushIcache: public AllStatic { ++ public: ++ static bool test(); ++ static void flush(uintptr_t start, uintptr_t end); ++}; ++ ++#endif // OS_LINUX_RISCV_FLUSH_ICACHE_LINUX_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp new file mode 100644 -index 00000000000..3100572e9fd +index 0000000000..ccceed643e --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -@@ -0,0 +1,92 @@ +@@ -0,0 +1,100 @@ +/* + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -57742,6 +53384,7 @@ index 00000000000..3100572e9fd + */ + +#include "precompiled.hpp" ++#include "memory/metaspaceShared.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/thread.inline.hpp" + @@ -57779,16 +53422,23 @@ index 00000000000..3100572e9fd + + intptr_t* ret_fp = NULL; + intptr_t* ret_sp = NULL; -+ address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); -+ if (addr == NULL || ret_sp == NULL ) { ++ ExtendedPC addr = os::Linux::fetch_frame_from_ucontext(this, uc, ++ &ret_sp, &ret_fp); ++ if (addr.pc() == NULL || ret_sp == NULL ) { + // ucontext wasn't useful + return false; + } + -+ frame ret_frame(ret_sp, ret_fp, addr); ++ if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { ++ // In the middle of a trampoline call. Bail out for safety. ++ // This happens rarely so shouldn't affect profiling. ++ return false; ++ } ++ ++ frame ret_frame(ret_sp, ret_fp, addr.pc()); + if (!ret_frame.safe_for_sender(this)) { +#ifdef COMPILER2 -+ frame ret_frame2(ret_sp, NULL, addr); ++ frame ret_frame2(ret_sp, NULL, addr.pc()); + if (!ret_frame2.safe_for_sender(this)) { + // nothing else to try if the frame isn't good + return false; @@ -57810,10 +53460,10 @@ index 00000000000..3100572e9fd +void JavaThread::cache_global_variables() { } diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp new file mode 100644 -index 00000000000..61e2cf85b63 +index 0000000000..4b91fa855a --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -@@ -0,0 +1,48 @@ +@@ -0,0 +1,67 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -57850,21 +53500,40 @@ index 00000000000..61e2cf85b63 + frame pd_last_frame(); + + public: ++ // Mutators are highly dangerous.... ++ intptr_t* last_Java_fp() { return _anchor.last_Java_fp(); } ++ void set_last_Java_fp(intptr_t* fp) { _anchor.set_last_Java_fp(fp); } ++ ++ void set_base_of_stack_pointer(intptr_t* base_sp) { ++ } ++ + static ByteSize last_Java_fp_offset() { + return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset(); + } + ++ intptr_t* base_of_stack_pointer() { ++ return NULL; ++ } ++ void record_base_of_stack_pointer() { ++ } ++ + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); +private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); ++public: ++ // These routines are only used on cpu architectures that ++ // have separate register stacks (Itanium). ++ static bool register_stack_overflow() { return false; } ++ static void enable_register_stack_guard() {} ++ static void disable_register_stack_guard() {} + +#endif // OS_CPU_LINUX_RISCV_THREAD_LINUX_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp new file mode 100644 -index 00000000000..6cf7683a586 +index 0000000000..6cf7683a58 --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/vmStructs_linux_riscv.hpp @@ -0,0 +1,55 @@ @@ -57925,10 +53594,10 @@ index 00000000000..6cf7683a586 +#endif // OS_CPU_LINUX_RISCV_VM_VMSTRUCTS_LINUX_RISCV_HPP 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 new file mode 100644 -index 00000000000..4623dbfad42 +index 0000000000..8bcc949fed --- /dev/null +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp -@@ -0,0 +1,118 @@ +@@ -0,0 +1,137 @@ +/* + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -57991,10 +53660,6 @@ index 00000000000..4623dbfad42 +#define HWCAP_ISA_V (1 << ('V' - 'A')) +#endif + -+#ifndef HWCAP_ISA_B -+#define HWCAP_ISA_B (1 << ('B' - 'A')) -+#endif -+ +#define read_csr(csr) \ +({ \ + register unsigned long __v; \ @@ -58010,18 +53675,35 @@ index 00000000000..4623dbfad42 + return (uint32_t)read_csr(CSR_VLENB); +} + ++VM_Version::VM_MODE VM_Version::get_satp_mode() { ++ if (!strcmp(_vm_mode, "sv39")) { ++ return VM_SV39; ++ } else if (!strcmp(_vm_mode, "sv48")) { ++ return VM_SV48; ++ } else if (!strcmp(_vm_mode, "sv57")) { ++ return VM_SV57; ++ } else if (!strcmp(_vm_mode, "sv64")) { ++ return VM_SV64; ++ } else { ++ return VM_MBARE; ++ } ++} ++ +void VM_Version::get_os_cpu_info() { + + uint64_t auxv = getauxval(AT_HWCAP); + -+ static_assert(CPU_I == HWCAP_ISA_I, "Flag CPU_I must follow Linux HWCAP"); -+ static_assert(CPU_M == HWCAP_ISA_M, "Flag CPU_M must follow Linux HWCAP"); -+ static_assert(CPU_A == HWCAP_ISA_A, "Flag CPU_A must follow Linux HWCAP"); -+ static_assert(CPU_F == HWCAP_ISA_F, "Flag CPU_F must follow Linux HWCAP"); -+ static_assert(CPU_D == HWCAP_ISA_D, "Flag CPU_D must follow Linux HWCAP"); -+ static_assert(CPU_C == HWCAP_ISA_C, "Flag CPU_C must follow Linux HWCAP"); -+ static_assert(CPU_V == HWCAP_ISA_V, "Flag CPU_V must follow Linux HWCAP"); -+ static_assert(CPU_B == HWCAP_ISA_B, "Flag CPU_B must follow Linux HWCAP"); ++ STATIC_ASSERT(CPU_I == HWCAP_ISA_I); ++ STATIC_ASSERT(CPU_M == HWCAP_ISA_M); ++ STATIC_ASSERT(CPU_A == HWCAP_ISA_A); ++ STATIC_ASSERT(CPU_F == HWCAP_ISA_F); ++ STATIC_ASSERT(CPU_D == HWCAP_ISA_D); ++ STATIC_ASSERT(CPU_C == HWCAP_ISA_C); ++ STATIC_ASSERT(CPU_V == HWCAP_ISA_V); ++ ++ // RISC-V has four bit-manipulation ISA-extensions: Zba/Zbb/Zbc/Zbs. ++ // Availability for those extensions could not be queried from HWCAP. ++ // TODO: Add proper detection for those extensions. + _features = auxv & ( + HWCAP_ISA_I | + HWCAP_ISA_M | @@ -58029,14 +53711,20 @@ index 00000000000..4623dbfad42 + HWCAP_ISA_F | + HWCAP_ISA_D | + HWCAP_ISA_C | -+ HWCAP_ISA_V | -+ HWCAP_ISA_B); ++ HWCAP_ISA_V); + + if (FILE *f = fopen("/proc/cpuinfo", "r")) { + char buf[512], *p; + while (fgets(buf, sizeof (buf), f) != NULL) { + if ((p = strchr(buf, ':')) != NULL) { -+ if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) { ++ if (strncmp(buf, "mmu", sizeof "mmu" - 1) == 0) { ++ if (_vm_mode[0] != '\0') { ++ continue; ++ } ++ char* vm_mode = os::strdup(p + 2); ++ vm_mode[strcspn(vm_mode, "\n")] = '\0'; ++ _vm_mode = vm_mode; ++ } else if (strncmp(buf, "uarch", sizeof "uarch" - 1) == 0) { + char* uarch = os::strdup(p + 2); + uarch[strcspn(uarch, "\n")] = '\0'; + _uarch = uarch; @@ -58048,7 +53736,7 @@ index 00000000000..4623dbfad42 + } +} diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp -index e30d39f73d1..733ee9e654c 100644 +index e30d39f73d..c640c546b1 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -1,5 +1,5 @@ @@ -58058,48 +53746,59 @@ index e30d39f73d1..733ee9e654c 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -199,7 +199,6 @@ bool LIR_OprDesc::is_oop() const { - void LIR_Op2::verify() const { +@@ -200,6 +200,9 @@ void LIR_Op2::verify() const { #ifdef ASSERT switch (code()) { -- case lir_cmove: + case lir_cmove: ++#ifdef RISCV ++ assert(false, "lir_cmove is LIR_Op4 on RISCV"); ++#endif case lir_xchg: break; -@@ -252,9 +251,7 @@ void LIR_Op2::verify() const { +@@ -252,9 +255,13 @@ void LIR_Op2::verify() const { LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block) -- : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) -- , _cond(cond) -- , _type(type) ++#ifdef RISCV + : LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL, type) ++#else + : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) + , _cond(cond) + , _type(type) ++#endif , _label(block->label()) , _block(block) , _ublock(NULL) -@@ -262,9 +259,7 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block +@@ -262,9 +269,13 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block } LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, CodeStub* stub) : -- LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) -- , _cond(cond) -- , _type(type) ++#ifdef RISCV + LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL, type) ++#else + LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) + , _cond(cond) + , _type(type) ++#endif , _label(stub->entry()) , _block(NULL) , _ublock(NULL) -@@ -272,9 +267,7 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, CodeStub* stub) : +@@ -272,9 +283,13 @@ LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, CodeStub* stub) : } LIR_OpBranch::LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block, BlockBegin* ublock) -- : LIR_Op(lir_cond_float_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) -- , _cond(cond) -- , _type(type) ++#ifdef RISCV + : LIR_Op2(lir_cond_float_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL, type) ++#else + : LIR_Op(lir_cond_float_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*)NULL) + , _cond(cond) + , _type(type) ++#endif , _label(block->label()) , _block(block) , _ublock(ublock) -@@ -296,13 +289,13 @@ void LIR_OpBranch::change_ublock(BlockBegin* b) { +@@ -296,13 +311,13 @@ void LIR_OpBranch::change_ublock(BlockBegin* b) { } void LIR_OpBranch::negate_cond() { @@ -58120,61 +53819,66 @@ index e30d39f73d1..733ee9e654c 100644 default: ShouldNotReachHere(); } } -@@ -525,6 +518,13 @@ void LIR_OpVisitState::visit(LIR_Op* op) { +@@ -525,6 +540,15 @@ void LIR_OpVisitState::visit(LIR_Op* op) { assert(op->as_OpBranch() != NULL, "must be"); LIR_OpBranch* opBranch = (LIR_OpBranch*)op; ++#ifdef RISCV + assert(opBranch->_tmp1->is_illegal() && opBranch->_tmp2->is_illegal() && + opBranch->_tmp3->is_illegal() && opBranch->_tmp4->is_illegal() && + opBranch->_tmp5->is_illegal(), "not used"); + + if (opBranch->_opr1->is_valid()) do_input(opBranch->_opr1); + if (opBranch->_opr2->is_valid()) do_input(opBranch->_opr2); ++#endif + if (opBranch->_info != NULL) do_info(opBranch->_info); assert(opBranch->_result->is_illegal(), "not used"); if (opBranch->_stub != NULL) opBranch->stub()->visit(this); -@@ -615,17 +615,19 @@ void LIR_OpVisitState::visit(LIR_Op* op) { +@@ -615,6 +639,21 @@ void LIR_OpVisitState::visit(LIR_Op* op) { // to the result operand, otherwise the backend fails case lir_cmove: { -- assert(op->as_Op2() != NULL, "must be"); -- LIR_Op2* op2 = (LIR_Op2*)op; ++#ifdef RISCV + assert(op->as_Op4() != NULL, "must be"); + LIR_Op4* op4 = (LIR_Op4*)op; - -- assert(op2->_info == NULL && op2->_tmp1->is_illegal() && op2->_tmp2->is_illegal() && -- op2->_tmp3->is_illegal() && op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used"); -- assert(op2->_opr1->is_valid() && op2->_opr2->is_valid() && op2->_result->is_valid(), "used"); ++ + assert(op4->_info == NULL && op4->_tmp1->is_illegal() && op4->_tmp2->is_illegal() && + op4->_tmp3->is_illegal() && op4->_tmp4->is_illegal() && op4->_tmp5->is_illegal(), "not used"); + assert(op4->_opr1->is_valid() && op4->_opr2->is_valid() && op4->_result->is_valid(), "used"); - -- do_input(op2->_opr1); -- do_input(op2->_opr2); -- do_temp(op2->_opr2); -- do_output(op2->_result); ++ + do_input(op4->_opr1); + do_input(op4->_opr2); + if (op4->_opr3->is_valid()) do_input(op4->_opr3); + if (op4->_opr4->is_valid()) do_input(op4->_opr4); + do_temp(op4->_opr2); + do_output(op4->_result); ++#else + assert(op->as_Op2() != NULL, "must be"); + LIR_Op2* op2 = (LIR_Op2*)op; + +@@ -626,6 +665,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { + do_input(op2->_opr2); + do_temp(op2->_opr2); + do_output(op2->_result); ++#endif break; } -@@ -1048,6 +1050,10 @@ void LIR_Op3::emit_code(LIR_Assembler* masm) { +@@ -1048,6 +1088,12 @@ void LIR_Op3::emit_code(LIR_Assembler* masm) { masm->emit_op3(this); } ++#ifdef RISCV +void LIR_Op4::emit_code(LIR_Assembler* masm) { + masm->emit_op4(this); +} ++#endif + void LIR_OpLock::emit_code(LIR_Assembler* masm) { masm->emit_lock(this); if (stub()) { -@@ -1084,6 +1090,10 @@ LIR_List::LIR_List(Compilation* compilation, BlockBegin* block) +@@ -1084,6 +1130,10 @@ LIR_List::LIR_List(Compilation* compilation, BlockBegin* block) , _file(NULL) , _line(0) #endif @@ -58185,7 +53889,7 @@ index e30d39f73d1..733ee9e654c 100644 { } -@@ -1101,6 +1111,38 @@ void LIR_List::set_file_and_line(const char * file, int line) { +@@ -1101,6 +1151,38 @@ void LIR_List::set_file_and_line(const char * file, int line) { } #endif @@ -58224,45 +53928,34 @@ index e30d39f73d1..733ee9e654c 100644 void LIR_List::append(LIR_InsertionBuffer* buffer) { assert(this == buffer->lir_list(), "wrong lir list"); -@@ -1680,7 +1722,6 @@ const char * LIR_Op::name() const { - case lir_cmp_l2i: s = "cmp_l2i"; break; - case lir_ucmp_fd2i: s = "ucomp_fd2i"; break; - case lir_cmp_fd2i: s = "comp_fd2i"; break; -- case lir_cmove: s = "cmove"; break; - case lir_add: s = "add"; break; - case lir_sub: s = "sub"; break; - case lir_mul: s = "mul"; break; -@@ -1705,6 +1746,8 @@ const char * LIR_Op::name() const { - case lir_irem: s = "irem"; break; - case lir_fmad: s = "fmad"; break; - case lir_fmaf: s = "fmaf"; break; -+ // LIR_Op4 -+ case lir_cmove: s = "cmove"; break; - // LIR_OpJavaCall - case lir_static_call: s = "static"; break; - case lir_optvirtual_call: s = "optvirtual"; break; -@@ -1841,6 +1884,8 @@ void LIR_Op1::print_patch_code(outputStream* out, LIR_PatchCode code) { +@@ -1841,6 +1923,10 @@ void LIR_Op1::print_patch_code(outputStream* out, LIR_PatchCode code) { // LIR_OpBranch void LIR_OpBranch::print_instr(outputStream* out) const { print_condition(out, cond()); out->print(" "); ++#ifdef RISCV + in_opr1()->print(out); out->print(" "); + in_opr2()->print(out); out->print(" "); ++#endif if (block() != NULL) { out->print("[B%d] ", block()->block_id()); } else if (stub() != NULL) { -@@ -1927,7 +1972,7 @@ void LIR_OpRoundFP::print_instr(outputStream* out) const { +@@ -1927,7 +2013,11 @@ void LIR_OpRoundFP::print_instr(outputStream* out) const { // LIR_Op2 void LIR_Op2::print_instr(outputStream* out) const { -- if (code() == lir_cmove || code() == lir_cmp) { ++#ifdef RISCV + if (code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch) { ++#else + if (code() == lir_cmove || code() == lir_cmp) { ++#endif print_condition(out, condition()); out->print(" "); } in_opr1()->print(out); out->print(" "); -@@ -1978,6 +2023,15 @@ void LIR_Op3::print_instr(outputStream* out) const { +@@ -1978,6 +2068,17 @@ void LIR_Op3::print_instr(outputStream* out) const { result_opr()->print(out); } ++#ifdef RISCV +// LIR_Op4 +void LIR_Op4::print_instr(outputStream* out) const { + print_condition(out, condition()); out->print(" "); @@ -58272,11 +53965,12 @@ index e30d39f73d1..733ee9e654c 100644 + in_opr4()->print(out); out->print(" "); + result_opr()->print(out); +} ++#endif void LIR_OpLock::print_instr(outputStream* out) const { hdr_opr()->print(out); out->print(" "); diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp -index 3234ca018b7..efff6bf7a30 100644 +index 3234ca018b..33943e369d 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -1,5 +1,5 @@ @@ -58286,52 +53980,62 @@ index 3234ca018b7..efff6bf7a30 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -867,6 +867,7 @@ class LIR_Op2; +@@ -867,6 +867,9 @@ class LIR_Op2; class LIR_OpDelay; class LIR_Op3; class LIR_OpAllocArray; ++#ifdef RISCV +class LIR_Op4; ++#endif class LIR_OpCall; class LIR_OpJavaCall; class LIR_OpRTCall; -@@ -916,8 +917,6 @@ enum LIR_Code { +@@ -916,8 +919,10 @@ enum LIR_Code { , lir_null_check , lir_return , lir_leal -- , lir_branch -- , lir_cond_float_branch ++#ifndef RISCV + , lir_branch + , lir_cond_float_branch ++#endif , lir_move , lir_convert , lir_alloc_object -@@ -929,11 +928,12 @@ enum LIR_Code { +@@ -929,11 +934,17 @@ enum LIR_Code { , lir_unwind , end_op1 , begin_op2 ++#ifdef RISCV + , lir_branch + , lir_cond_float_branch ++#endif , lir_cmp , lir_cmp_l2i , lir_ucmp_fd2i , lir_cmp_fd2i -- , lir_cmove ++#ifndef RISCV + , lir_cmove ++#endif , lir_add , lir_sub , lir_mul -@@ -964,6 +964,9 @@ enum LIR_Code { +@@ -964,6 +975,11 @@ enum LIR_Code { , lir_fmad , lir_fmaf , end_op3 ++#ifdef RISCV + , begin_op4 + , lir_cmove + , end_op4 ++#endif , begin_opJavaCall , lir_static_call , lir_optvirtual_call -@@ -1001,6 +1004,11 @@ enum LIR_Code { +@@ -1001,6 +1017,11 @@ enum LIR_Code { , begin_opAssert , lir_assert , end_opAssert -+#ifdef INCLUDE_ZGC ++#if defined(RISCV) && defined(INCLUDE_ZGC) + , begin_opZLoadBarrierTest + , lir_zloadbarrier_test + , end_opZLoadBarrierTest @@ -58339,15 +54043,17 @@ index 3234ca018b7..efff6bf7a30 100644 }; -@@ -1134,6 +1142,7 @@ class LIR_Op: public CompilationResourceObj { +@@ -1134,6 +1155,9 @@ class LIR_Op: public CompilationResourceObj { virtual LIR_Op1* as_Op1() { return NULL; } virtual LIR_Op2* as_Op2() { return NULL; } virtual LIR_Op3* as_Op3() { return NULL; } ++#ifdef RISCV + virtual LIR_Op4* as_Op4() { return NULL; } ++#endif virtual LIR_OpArrayCopy* as_OpArrayCopy() { return NULL; } virtual LIR_OpUpdateCRC32* as_OpUpdateCRC32() { return NULL; } virtual LIR_OpTypeCheck* as_OpTypeCheck() { return NULL; } -@@ -1410,51 +1419,6 @@ class LIR_OpRTCall: public LIR_OpCall { +@@ -1410,51 +1434,6 @@ class LIR_OpRTCall: public LIR_OpCall { virtual void verify() const; }; @@ -58399,7 +54105,7 @@ index 3234ca018b7..efff6bf7a30 100644 class ConversionStub; class LIR_OpConvert: public LIR_Op1 { -@@ -1614,19 +1578,19 @@ class LIR_Op2: public LIR_Op { +@@ -1614,19 +1593,19 @@ class LIR_Op2: public LIR_Op { void verify() const; public: @@ -58420,11 +54126,11 @@ index 3234ca018b7..efff6bf7a30 100644 - assert(code == lir_cmp || code == lir_assert, "code check"); + , _tmp5(LIR_OprFact::illegalOpr) + , _condition(condition) { -+ assert(code == lir_cmp || code == lir_branch || code == lir_cond_float_branch || code == lir_assert, "code check"); ++ assert(code == lir_cmp || code == lir_assert RISCV_ONLY(|| code == lir_branch || code == lir_cond_float_branch), "code check"); } LIR_Op2(LIR_Code code, LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) -@@ -1651,14 +1615,14 @@ class LIR_Op2: public LIR_Op { +@@ -1651,14 +1630,14 @@ class LIR_Op2: public LIR_Op { , _opr1(opr1) , _opr2(opr2) , _type(type) @@ -58438,11 +54144,11 @@ index 3234ca018b7..efff6bf7a30 100644 - assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); + , _tmp5(LIR_OprFact::illegalOpr) + , _condition(lir_cond_unknown) { -+ assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check"); ++ assert(code != lir_cmp && RISCV_ONLY(code != lir_branch && code != lir_cond_float_branch &&) is_in_range(code, begin_op2, end_op2), "code check"); } LIR_Op2(LIR_Code code, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, LIR_Opr tmp1, LIR_Opr tmp2 = LIR_OprFact::illegalOpr, -@@ -1667,14 +1631,14 @@ class LIR_Op2: public LIR_Op { +@@ -1667,14 +1646,14 @@ class LIR_Op2: public LIR_Op { , _opr1(opr1) , _opr2(opr2) , _type(T_ILLEGAL) @@ -58456,31 +54162,45 @@ index 3234ca018b7..efff6bf7a30 100644 - assert(code != lir_cmp && is_in_range(code, begin_op2, end_op2), "code check"); + , _tmp5(tmp5) + , _condition(lir_cond_unknown) { -+ assert(code != lir_cmp && code != lir_branch && code != lir_cond_float_branch && is_in_range(code, begin_op2, end_op2), "code check"); ++ assert(code != lir_cmp && RISCV_ONLY(code != lir_branch && code != lir_cond_float_branch &&) is_in_range(code, begin_op2, end_op2), "code check"); } LIR_Opr in_opr1() const { return _opr1; } -@@ -1686,10 +1650,10 @@ class LIR_Op2: public LIR_Op { +@@ -1686,10 +1665,18 @@ class LIR_Op2: public LIR_Op { LIR_Opr tmp4_opr() const { return _tmp4; } LIR_Opr tmp5_opr() const { return _tmp5; } LIR_Condition condition() const { -- assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition; ++#ifdef RISCV + assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch || code() == lir_assert, "only valid for branch and assert"); return _condition; ++#else + assert(code() == lir_cmp || code() == lir_cmove || code() == lir_assert, "only valid for cmp and cmove and assert"); return _condition; ++#endif } void set_condition(LIR_Condition condition) { -- assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition; ++#ifdef RISCV + assert(code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch, "only valid for branch"); _condition = condition; ++#else + assert(code() == lir_cmp || code() == lir_cmove, "only valid for cmp and cmove"); _condition = condition; ++#endif } void set_fpu_stack_size(int size) { _fpu_stack_size = size; } -@@ -1703,6 +1667,51 @@ class LIR_Op2: public LIR_Op { +@@ -1703,6 +1690,65 @@ class LIR_Op2: public LIR_Op { virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; ++#ifdef RISCV +class LIR_OpBranch: public LIR_Op2 { ++#else ++class LIR_OpBranch: public LIR_Op { ++#endif + friend class LIR_OpVisitState; + + private: ++#ifndef RISCV ++ LIR_Condition _cond; ++ BasicType _type; ++#endif + Label* _label; + BlockBegin* _block; // if this is a branch to a block, this is the block + BlockBegin* _ublock; // if this is a float-branch, this is the unorderd block @@ -58488,7 +54208,13 @@ index 3234ca018b7..efff6bf7a30 100644 + + public: + LIR_OpBranch(LIR_Condition cond, BasicType type, Label* lbl) ++#ifdef RISCV + : LIR_Op2(lir_branch, cond, LIR_OprFact::illegalOpr, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL, type) ++#else ++ : LIR_Op(lir_branch, LIR_OprFact::illegalOpr, (CodeEmitInfo*) NULL) ++ , _cond(cond) ++ , _type(type) ++#endif + , _label(lbl) + , _block(NULL) + , _ublock(NULL) @@ -58500,14 +54226,14 @@ index 3234ca018b7..efff6bf7a30 100644 + // for unordered comparisons + LIR_OpBranch(LIR_Condition cond, BasicType type, BlockBegin* block, BlockBegin* ublock); + -+ LIR_Condition cond() const { -+ return condition(); -+ } -+ -+ void set_cond(LIR_Condition cond) { -+ set_condition(cond); -+ } -+ ++#ifdef RISCV ++ LIR_Condition cond() const { return condition(); } ++ void set_cond(LIR_Condition cond) { set_condition(cond); } ++#else ++ LIR_Condition cond() const { return _cond; } ++ void set_cond(LIR_Condition cond) { _cond = cond; } ++#endif ++ BasicType type() const { return _type; } + Label* label() const { return _label; } + BlockBegin* block() const { return _block; } + BlockBegin* ublock() const { return _ublock; } @@ -58525,10 +54251,11 @@ index 3234ca018b7..efff6bf7a30 100644 class LIR_OpAllocArray : public LIR_Op { friend class LIR_OpVisitState; -@@ -1766,6 +1775,63 @@ class LIR_Op3: public LIR_Op { +@@ -1766,6 +1812,65 @@ class LIR_Op3: public LIR_Op { virtual void print_instr(outputStream* out) const PRODUCT_RETURN; }; ++#ifdef RISCV +class LIR_Op4: public LIR_Op { + friend class LIR_OpVisitState; + protected: @@ -58586,10 +54313,11 @@ index 3234ca018b7..efff6bf7a30 100644 + + virtual void print_instr(outputStream* out) const PRODUCT_RETURN; +}; ++#endif //-------------------------------- class LabelObj: public CompilationResourceObj { -@@ -1988,6 +2054,10 @@ class LIR_List: public CompilationResourceObj { +@@ -1988,6 +2093,10 @@ class LIR_List: public CompilationResourceObj { const char * _file; int _line; #endif @@ -58600,7 +54328,7 @@ index 3234ca018b7..efff6bf7a30 100644 public: void append(LIR_Op* op) { -@@ -2000,6 +2070,12 @@ class LIR_List: public CompilationResourceObj { +@@ -2000,6 +2109,12 @@ class LIR_List: public CompilationResourceObj { } #endif // PRODUCT @@ -58613,7 +54341,7 @@ index 3234ca018b7..efff6bf7a30 100644 _operations.append(op); #ifdef ASSERT -@@ -2016,6 +2092,10 @@ class LIR_List: public CompilationResourceObj { +@@ -2016,6 +2131,10 @@ class LIR_List: public CompilationResourceObj { void set_file_and_line(const char * file, int line); #endif @@ -58624,37 +54352,44 @@ index 3234ca018b7..efff6bf7a30 100644 //---------- accessors --------------- LIR_OpList* instructions_list() { return &_operations; } int length() const { return _operations.length(); } -@@ -2149,8 +2229,9 @@ class LIR_List: public CompilationResourceObj { +@@ -2149,9 +2268,16 @@ class LIR_List: public CompilationResourceObj { void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info); void cmp_reg_mem(LIR_Condition condition, LIR_Opr reg, LIR_Address* addr, CodeEmitInfo* info); -- void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { -- append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); ++#ifdef RISCV + void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type, + LIR_Opr cmp_opr1 = LIR_OprFact::illegalOpr, LIR_Opr cmp_opr2 = LIR_OprFact::illegalOpr) { + append(new LIR_Op4(lir_cmove, condition, src1, src2, cmp_opr1, cmp_opr2, dst, type)); ++ } ++#else + void cmove(LIR_Condition condition, LIR_Opr src1, LIR_Opr src2, LIR_Opr dst, BasicType type) { + append(new LIR_Op2(lir_cmove, condition, src1, src2, dst, type)); } ++#endif void cas_long(LIR_Opr addr, LIR_Opr cmp_value, LIR_Opr new_value, + LIR_Opr t1, LIR_Opr t2, LIR_Opr result = LIR_OprFact::illegalOpr); diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp -index 160483d5f74..42a0350f7d9 100644 +index 160483d5f7..68aec26c1e 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp -@@ -709,10 +709,6 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { +@@ -709,9 +709,11 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { comp_fl2i(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op); break; -- case lir_cmove: -- cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type()); -- break; -- ++#ifndef RISCV + case lir_cmove: + cmove(op->condition(), op->in_opr1(), op->in_opr2(), op->result_opr(), op->type()); + break; ++#endif + case lir_shl: case lir_shr: - case lir_ushr: -@@ -776,6 +772,17 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { +@@ -776,6 +778,19 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { } } ++#ifdef RISCV +void LIR_Assembler::emit_op4(LIR_Op4* op) { + switch(op->code()) { + case lir_cmove: @@ -58666,34 +54401,40 @@ index 160483d5f74..42a0350f7d9 100644 + break; + } +} ++#endif void LIR_Assembler::build_frame() { _masm->build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); diff --git a/src/hotspot/share/c1/c1_LIRAssembler.hpp b/src/hotspot/share/c1/c1_LIRAssembler.hpp -index 44a5bcbe542..c677bd346fc 100644 +index 44a5bcbe54..baeb4aa442 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.hpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp -@@ -190,6 +190,7 @@ class LIR_Assembler: public CompilationResourceObj { +@@ -190,6 +190,9 @@ class LIR_Assembler: public CompilationResourceObj { void emit_op1(LIR_Op1* op); void emit_op2(LIR_Op2* op); void emit_op3(LIR_Op3* op); ++#ifdef RISCV + void emit_op4(LIR_Op4* op); ++#endif void emit_opBranch(LIR_OpBranch* op); void emit_opLabel(LIR_OpLabel* op); void emit_arraycopy(LIR_OpArrayCopy* op); -@@ -222,8 +223,8 @@ class LIR_Assembler: public CompilationResourceObj { +@@ -222,8 +225,12 @@ class LIR_Assembler: public CompilationResourceObj { void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); void comp_mem_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info); // info set for null exceptions void comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr result, LIR_Op2* op); -- void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); -- ++#ifdef RISCV + void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type, + LIR_Opr cmp_opr1 = LIR_OprFact::illegalOpr, LIR_Opr cmp_opr2 = LIR_OprFact::illegalOpr); ++#else + void cmove(LIR_Condition code, LIR_Opr left, LIR_Opr right, LIR_Opr result, BasicType type); +- ++#endif void call( LIR_OpJavaCall* op, relocInfo::relocType rtype); void ic_call( LIR_OpJavaCall* op); void vtable_call( LIR_OpJavaCall* op); diff --git a/src/hotspot/share/c1/c1_LinearScan.cpp b/src/hotspot/share/c1/c1_LinearScan.cpp -index c28055fd996..a4dfe8552ae 100644 +index acc969ac9c..512b63c744 100644 --- a/src/hotspot/share/c1/c1_LinearScan.cpp +++ b/src/hotspot/share/c1/c1_LinearScan.cpp @@ -1,5 +1,5 @@ @@ -58703,22 +54444,21 @@ index c28055fd996..a4dfe8552ae 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -1242,11 +1242,11 @@ void LinearScan::add_register_hints(LIR_Op* op) { +@@ -1242,8 +1242,13 @@ void LinearScan::add_register_hints(LIR_Op* op) { break; } case lir_cmove: { -- assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2"); -- LIR_Op2* cmove = (LIR_Op2*)op; ++#ifdef RISCV + assert(op->as_Op4() != NULL, "lir_cmove must be LIR_Op4"); + LIR_Op4* cmove = (LIR_Op4*)op; ++#else + assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2"); + LIR_Op2* cmove = (LIR_Op2*)op; ++#endif LIR_Opr move_from = cmove->in_opr1(); -- LIR_Opr move_to = cmove->result_opr(); -+ LIR_Opr move_to = cmove->result_opr(); - - if (move_to->is_register() && move_from->is_register()) { - Interval* from = interval_at(reg_num(move_from)); -@@ -3140,6 +3140,9 @@ void LinearScan::do_linear_scan() { + LIR_Opr move_to = cmove->result_opr(); +@@ -3148,6 +3153,9 @@ void LinearScan::do_linear_scan() { } } @@ -58728,7 +54468,7 @@ index c28055fd996..a4dfe8552ae 100644 { TIME_LINEAR_SCAN(timer_optimize_lir); EdgeMoveOptimizer::optimize(ir()->code()); -@@ -3147,6 +3150,7 @@ void LinearScan::do_linear_scan() { +@@ -3155,6 +3163,7 @@ void LinearScan::do_linear_scan() { // check that cfg is still correct after optimizations ir()->verify(); } @@ -58736,26 +54476,32 @@ index c28055fd996..a4dfe8552ae 100644 NOT_PRODUCT(print_lir(1, "Before Code Generation", false)); NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final)); -@@ -6284,14 +6288,14 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { +@@ -6292,14 +6301,23 @@ void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) { // 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 // to take care of this cmove as well. -- LIR_Op2* prev_cmove = NULL; ++#ifdef RISCV + LIR_Op4* prev_cmove = NULL; ++#else + LIR_Op2* prev_cmove = NULL; ++#endif for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) { prev_op = instructions->at(j); // check for the cmove if (prev_op->code() == lir_cmove) { -- assert(prev_op->as_Op2() != NULL, "cmove must be of type LIR_Op2"); -- prev_cmove = (LIR_Op2*)prev_op; ++#ifdef RISCV + assert(prev_op->as_Op4() != NULL, "cmove must be of type LIR_Op4"); + prev_cmove = (LIR_Op4*)prev_op; ++#else + assert(prev_op->as_Op2() != NULL, "cmove must be of type LIR_Op2"); + prev_cmove = (LIR_Op2*)prev_op; ++#endif assert(prev_branch->cond() == prev_cmove->condition(), "should be the same"); } if (prev_op->code() == lir_cmp) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp -index 4771a8b8652..6d377fa005d 100644 +index 4771a8b865..6d377fa005 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -1,5 +1,5 @@ @@ -58775,7 +54521,7 @@ index 4771a8b8652..6d377fa005d 100644 #endif diff --git a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp -index 9f8ce742433..f36dd612eff 100644 +index 9f8ce74243..125cc169be 100644 --- a/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp +++ b/src/hotspot/share/gc/z/c1/zBarrierSetC1.cpp @@ -1,5 +1,5 @@ @@ -58785,17 +54531,20 @@ index 9f8ce742433..f36dd612eff 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -100,7 +100,7 @@ class LIR_OpZLoadBarrierTest : public LIR_Op { +@@ -100,7 +100,11 @@ private: public: LIR_OpZLoadBarrierTest(LIR_Opr opr) : -- LIR_Op(), ++#ifdef RISCV + LIR_Op(lir_zloadbarrier_test, LIR_OprFact::illegalOpr, NULL), ++#else + LIR_Op(), ++#endif _opr(opr) {} virtual void visit(LIR_OpVisitState* state) { diff --git a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp -index e01a242a57e..ff16de0e778 100644 +index e01a242a57..ff16de0e77 100644 --- a/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp +++ b/src/hotspot/share/jfr/utilities/jfrBigEndian.hpp @@ -102,7 +102,7 @@ inline T JfrBigEndian::read_unaligned(const address location) { @@ -58807,19 +54556,8 @@ index e01a242a57e..ff16de0e778 100644 return false; #else #warning "Unconfigured platform" -diff --git a/src/hotspot/share/opto/regmask.hpp b/src/hotspot/share/opto/regmask.hpp -index c64d0879592..bc856d4b617 100644 ---- a/src/hotspot/share/opto/regmask.hpp -+++ b/src/hotspot/share/opto/regmask.hpp -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1997, 2022, 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 diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp -index c46247f2bdb..b5e64b65ff7 100644 +index a383297611..5e9228e705 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -196,7 +196,8 @@ const char* Abstract_VM_Version::jre_release_version() { @@ -58832,22 +54570,11 @@ index c46247f2bdb..b5e64b65ff7 100644 #endif // !ZERO #endif // !CPU -diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp -index e7b32723e47..434826853ee 100644 ---- a/src/hotspot/share/runtime/synchronizer.cpp -+++ b/src/hotspot/share/runtime/synchronizer.cpp -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 1998, 2022, 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 diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp -index aa914eccafc..a2f98e6a251 100644 +index 8ac6d63586..6bb38c40cc 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp -@@ -1234,7 +1234,7 @@ class JavaThread: public Thread { +@@ -1261,7 +1261,7 @@ class JavaThread: public Thread { address last_Java_pc(void) { return _anchor.last_Java_pc(); } // Safepoint support @@ -58857,7 +54584,7 @@ index aa914eccafc..a2f98e6a251 100644 void set_thread_state(JavaThreadState s) { assert(current_or_null() == NULL || current_or_null() == this, diff --git a/src/hotspot/share/runtime/thread.inline.hpp b/src/hotspot/share/runtime/thread.inline.hpp -index dee8534f739..9af07aeb459 100644 +index dee8534f73..9af07aeb45 100644 --- a/src/hotspot/share/runtime/thread.inline.hpp +++ b/src/hotspot/share/runtime/thread.inline.hpp @@ -1,5 +1,5 @@ @@ -58877,10 +54604,10 @@ index dee8534f739..9af07aeb459 100644 return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state); } diff --git a/src/hotspot/share/utilities/macros.hpp b/src/hotspot/share/utilities/macros.hpp -index cf802538689..e8ab3097ac7 100644 +index 6605ab367c..7f1bcff6b3 100644 --- a/src/hotspot/share/utilities/macros.hpp +++ b/src/hotspot/share/utilities/macros.hpp -@@ -597,6 +597,32 @@ +@@ -601,6 +601,32 @@ #define MACOS_AARCH64_ONLY(x) MACOS_ONLY(AARCH64_ONLY(x)) @@ -58913,8 +54640,101 @@ index cf802538689..e8ab3097ac7 100644 #ifdef VM_LITTLE_ENDIAN #define LITTLE_ENDIAN_ONLY(code) code #define BIG_ENDIAN_ONLY(code) +diff --git a/src/hotspot/share/utilities/vmassert_reinstall.hpp b/src/hotspot/share/utilities/vmassert_reinstall.hpp +new file mode 100644 +index 0000000000..32d31ac0c4 +--- /dev/null ++++ b/src/hotspot/share/utilities/vmassert_reinstall.hpp +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * 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. ++ * ++ */ ++ ++// Intentionally no #include guard. May be included multiple times for effect. ++ ++// See vmassert_uninstall.hpp for usage. ++ ++// Remove possible stdlib assert macro (or any others, for that matter). ++#undef assert ++ ++// Reinstall HotSpot's assert macro, if previously defined. ++#ifdef vmassert ++#define assert(p, ...) vmassert(p, __VA_ARGS__) ++#endif ++ +diff --git a/src/hotspot/share/utilities/vmassert_uninstall.hpp b/src/hotspot/share/utilities/vmassert_uninstall.hpp +new file mode 100644 +index 0000000000..dd6d51633d +--- /dev/null ++++ b/src/hotspot/share/utilities/vmassert_uninstall.hpp +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * 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. ++ * ++ */ ++ ++// Intentionally no #include guard. May be included multiple times for effect. ++ ++// The files vmassert_uninstall.hpp and vmassert_reinstall.hpp provide a ++// workaround for the name collision between HotSpot's assert macro and the ++// Standard Library's assert macro. When including a 3rd-party header that ++// uses (and so includes) the standard assert macro, wrap that inclusion with ++// includes of these two files, e.g. ++// ++// #include "utilities/vmassert_uninstall.hpp" ++// #include
++// #include "utilities/vmassert_reinstall.hpp" ++// ++// This removes the HotSpot macro definition while pre-processing the ++// 3rd-party header, then reinstates the HotSpot macro (if previously defined) ++// for following code. ++ ++// Remove HotSpot's assert macro, if present. ++#ifdef vmassert ++#undef assert ++#endif // vmassert ++ diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -index 0d834302c57..45a927fb5ee 100644 +index 0d834302c5..45a927fb5e 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c @@ -1,5 +1,5 @@ @@ -59000,7 +54820,7 @@ index 0d834302c57..45a927fb5ee 100644 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_ppc64_PPC64ThreadContext_##reg diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h -index 8318e8e0213..ab092d4ee33 100644 +index 8318e8e021..ab092d4ee3 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/libproc.h @@ -1,5 +1,5 @@ @@ -59020,10 +54840,10 @@ index 8318e8e0213..ab092d4ee33 100644 // This C bool type must be int for compatibility with Linux calls and diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java -index 0f5f0119c73..9bff9ee9b15 100644 +index 0f5f0119c7..9bff9ee9b1 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/HotSpotAgent.java -@@ -36,6 +36,7 @@ +@@ -36,6 +36,7 @@ import sun.jvm.hotspot.debugger.MachineDescription; import sun.jvm.hotspot.debugger.MachineDescriptionAMD64; import sun.jvm.hotspot.debugger.MachineDescriptionPPC64; import sun.jvm.hotspot.debugger.MachineDescriptionAArch64; @@ -59031,7 +54851,7 @@ index 0f5f0119c73..9bff9ee9b15 100644 import sun.jvm.hotspot.debugger.MachineDescriptionIntelX86; import sun.jvm.hotspot.debugger.MachineDescriptionSPARC32Bit; import sun.jvm.hotspot.debugger.MachineDescriptionSPARC64Bit; -@@ -598,6 +599,8 @@ private void setupDebuggerLinux() { +@@ -598,6 +599,8 @@ public class HotSpotAgent { } else { machDesc = new MachineDescriptionSPARC32Bit(); } @@ -59042,7 +54862,7 @@ index 0f5f0119c73..9bff9ee9b15 100644 machDesc = (MachineDescription) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java new file mode 100644 -index 00000000000..a972516dee3 +index 0000000000..a972516dee --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/MachineDescriptionRISCV64.java @@ -0,0 +1,40 @@ @@ -59087,7 +54907,7 @@ index 00000000000..a972516dee3 + } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java -index 5e5a6bb7141..dc0bcb3da94 100644 +index 5e5a6bb714..dc0bcb3da9 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java @@ -1,5 +1,5 @@ @@ -59097,7 +54917,7 @@ index 5e5a6bb7141..dc0bcb3da94 100644 * Copyright (c) 2015, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * -@@ -34,12 +34,14 @@ +@@ -34,12 +34,14 @@ import sun.jvm.hotspot.debugger.x86.*; import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.debugger.aarch64.*; import sun.jvm.hotspot.debugger.sparc.*; @@ -59112,7 +54932,7 @@ index 5e5a6bb7141..dc0bcb3da94 100644 import sun.jvm.hotspot.utilities.*; class LinuxCDebugger implements CDebugger { -@@ -116,7 +118,14 @@ public CFrame topFrameForThread(ThreadProxy thread) throws DebuggerException { +@@ -116,7 +118,14 @@ class LinuxCDebugger implements CDebugger { Address pc = context.getRegisterAsAddress(AARCH64ThreadContext.PC); if (pc == null) return null; return new LinuxAARCH64CFrame(dbg, fp, pc); @@ -59130,7 +54950,7 @@ index 5e5a6bb7141..dc0bcb3da94 100644 return context.getTopFrame(dbg); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java new file mode 100644 -index 00000000000..f06da24bd0e +index 0000000000..f06da24bd0 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64CFrame.java @@ -0,0 +1,90 @@ @@ -59226,7 +55046,7 @@ index 00000000000..f06da24bd0e +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java new file mode 100644 -index 00000000000..fdb841ccf3d +index 0000000000..fdb841ccf3 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/riscv64/LinuxRISCV64ThreadContext.java @@ -0,0 +1,48 @@ @@ -59280,7 +55100,7 @@ index 00000000000..fdb841ccf3d +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java new file mode 100644 -index 00000000000..96d5dee47ce +index 0000000000..96d5dee47c --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64Thread.java @@ -0,0 +1,88 @@ @@ -59374,7 +55194,7 @@ index 00000000000..96d5dee47ce +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java new file mode 100644 -index 00000000000..f2aa845e665 +index 0000000000..f2aa845e66 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadContext.java @@ -0,0 +1,48 @@ @@ -59428,7 +55248,7 @@ index 00000000000..f2aa845e665 +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java new file mode 100644 -index 00000000000..19f64b8ce2d +index 0000000000..19f64b8ce2 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/proc/riscv64/ProcRISCV64ThreadFactory.java @@ -0,0 +1,46 @@ @@ -59480,7 +55300,7 @@ index 00000000000..19f64b8ce2d +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java new file mode 100644 -index 00000000000..aecbda59023 +index 0000000000..aecbda5902 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64Thread.java @@ -0,0 +1,55 @@ @@ -59541,7 +55361,7 @@ index 00000000000..aecbda59023 +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java new file mode 100644 -index 00000000000..1d3da6be5af +index 0000000000..1d3da6be5a --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadContext.java @@ -0,0 +1,48 @@ @@ -59595,7 +55415,7 @@ index 00000000000..1d3da6be5af +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java new file mode 100644 -index 00000000000..725b94e25a3 +index 0000000000..725b94e25a --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/remote/riscv64/RemoteRISCV64ThreadFactory.java @@ -0,0 +1,46 @@ @@ -59645,11 +55465,11 @@ index 00000000000..725b94e25a3 + return new RemoteRISCV64Thread(debugger, id); + } +} -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/risv64/RISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/risv64/RISCV64ThreadContext.java +diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java new file mode 100644 -index 00000000000..fb60a70427a +index 0000000000..fb60a70427 --- /dev/null -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/risv64/RISCV64ThreadContext.java ++++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/riscv64/RISCV64ThreadContext.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. @@ -59824,7 +55644,7 @@ index 00000000000..fb60a70427a + public abstract Address getRegisterAsAddress(int index); +} 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 190062785a7..89d676fe3b9 100644 +index 190062785a..89d676fe3b 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 @@ -1,5 +1,5 @@ @@ -59834,7 +55654,7 @@ index 190062785a7..89d676fe3b9 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -38,6 +38,7 @@ +@@ -38,6 +38,7 @@ import sun.jvm.hotspot.runtime.win32_aarch64.Win32AARCH64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_x86.LinuxX86JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_amd64.LinuxAMD64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_aarch64.LinuxAARCH64JavaThreadPDAccess; @@ -59842,7 +55662,7 @@ index 190062785a7..89d676fe3b9 100644 import sun.jvm.hotspot.runtime.linux_ppc64.LinuxPPC64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.linux_sparc.LinuxSPARCJavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess; -@@ -99,6 +100,8 @@ private static synchronized void initialize(TypeDataBase db) { +@@ -99,6 +100,8 @@ public class Threads { access = new LinuxPPC64JavaThreadPDAccess(); } else if (cpu.equals("aarch64")) { access = new LinuxAARCH64JavaThreadPDAccess(); @@ -59853,10 +55673,10 @@ index 190062785a7..89d676fe3b9 100644 access = (JavaThreadPDAccess) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java new file mode 100644 -index 00000000000..f2e224f28ee +index 0000000000..5c2b6e0e3e --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java -@@ -0,0 +1,134 @@ +@@ -0,0 +1,132 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. @@ -59893,8 +55713,6 @@ index 00000000000..f2e224f28ee +import sun.jvm.hotspot.runtime.riscv64.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; -+import sun.jvm.hotspot.utilities.Observable; -+import sun.jvm.hotspot.utilities.Observer; + +public class LinuxRISCV64JavaThreadPDAccess implements JavaThreadPDAccess { + private static AddressField lastJavaFPField; @@ -59993,7 +55811,7 @@ index 00000000000..f2e224f28ee +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java new file mode 100644 -index 00000000000..34701c6922f +index 0000000000..34701c6922 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64CurrentFrameGuess.java @@ -0,0 +1,223 @@ @@ -60222,10 +56040,10 @@ index 00000000000..34701c6922f +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java new file mode 100644 -index 00000000000..df280005d72 +index 0000000000..e372bc5f7b --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java -@@ -0,0 +1,556 @@ +@@ -0,0 +1,554 @@ +/* + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Red Hat Inc. @@ -60262,8 +56080,6 @@ index 00000000000..df280005d72 +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; -+import sun.jvm.hotspot.utilities.Observable; -+import sun.jvm.hotspot.utilities.Observer; + +/** Specialization of and implementation of abstract methods of the + Frame class for the riscv64 family of CPUs. */ @@ -60784,10 +56600,10 @@ index 00000000000..df280005d72 +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java new file mode 100644 -index 00000000000..d0ad2b559a6 +index 0000000000..850758a7ed --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java -@@ -0,0 +1,61 @@ +@@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, Red Hat Inc. @@ -60821,8 +56637,6 @@ index 00000000000..d0ad2b559a6 +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.utilities.*; -+import sun.jvm.hotspot.utilities.Observable; -+import sun.jvm.hotspot.utilities.Observer; + +public class RISCV64JavaCallWrapper extends JavaCallWrapper { + private static AddressField lastJavaFPField; @@ -60851,7 +56665,7 @@ index 00000000000..d0ad2b559a6 +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java new file mode 100644 -index 00000000000..4aeb1c6f557 +index 0000000000..4aeb1c6f55 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64RegisterMap.java @@ -0,0 +1,53 @@ @@ -60909,7 +56723,7 @@ index 00000000000..4aeb1c6f557 + protected Address getLocationPD(VMReg reg) { return null; } +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java -index 7d7a6107cab..6552ce255fc 100644 +index 7d7a6107ca..6552ce255f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PlatformInfo.java @@ -1,5 +1,5 @@ @@ -60919,7 +56733,7 @@ index 7d7a6107cab..6552ce255fc 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -54,7 +54,7 @@ public static String getOS() throws UnsupportedPlatformException { +@@ -54,7 +54,7 @@ public class PlatformInfo { public static boolean knownCPU(String cpu) { final String[] KNOWN = @@ -60928,8 +56742,88 @@ index 7d7a6107cab..6552ce255fc 100644 for(String s : KNOWN) { if(s.equals(cpu)) +diff --git a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp +index 24f25b87af..7a3845e336 100644 +--- a/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp ++++ b/test/hotspot/gtest/gc/shared/test_memset_with_concurrent_readers.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2016, 2022, 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 +@@ -24,10 +24,13 @@ + #include "precompiled.hpp" + #include "gc/shared/memset_with_concurrent_readers.hpp" + #include "utilities/globalDefinitions.hpp" +-#include "unittest.hpp" + ++#include "utilities/vmassert_uninstall.hpp" + #include + #include ++#include "utilities/vmassert_reinstall.hpp" ++ ++#include "unittest.hpp" + + static unsigned line_byte(const char* line, size_t i) { + return unsigned(line[i]) & 0xFF; +diff --git a/test/hotspot/gtest/jfr/test_networkUtilization.cpp b/test/hotspot/gtest/jfr/test_networkUtilization.cpp +index 19d6a6e2c2..42cd18356b 100644 +--- a/test/hotspot/gtest/jfr/test_networkUtilization.cpp ++++ b/test/hotspot/gtest/jfr/test_networkUtilization.cpp +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 2022, 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 +@@ -42,11 +42,13 @@ + #include "utilities/globalDefinitions.hpp" + #include "utilities/growableArray.hpp" + +-#include "unittest.hpp" +- ++#include "utilities/vmassert_uninstall.hpp" + #include + #include + #include ++#include "utilities/vmassert_reinstall.hpp" ++ ++#include "unittest.hpp" + + namespace { + +diff --git a/test/hotspot/gtest/unittest.hpp b/test/hotspot/gtest/unittest.hpp +index 0494a0e240..91edf6adba 100644 +--- a/test/hotspot/gtest/unittest.hpp ++++ b/test/hotspot/gtest/unittest.hpp +@@ -28,19 +28,10 @@ + #include + + #define GTEST_DONT_DEFINE_TEST 1 +-#include "gtest/gtest.h" + +-// gtest/gtest.h includes assert.h which will define the assert macro, but hotspot has its +-// own standards incompatible assert macro that takes two parameters. +-// The workaround is to undef assert and then re-define it. The re-definition +-// must unfortunately be copied since debug.hpp might already have been +-// included and a second include wouldn't work due to the header guards in debug.hpp. +-#ifdef assert +- #undef assert +- #ifdef vmassert +- #define assert(p, ...) vmassert(p, __VA_ARGS__) +- #endif +-#endif ++#include "utilities/vmassert_uninstall.hpp" ++#include "gtest/gtest.h" ++#include "utilities/vmassert_reinstall.hpp" + + #define CONCAT(a, b) a ## b + diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java -index 7805918c28a..823b9f39dbf 100644 +index 7805918c28..823b9f39db 100644 --- a/test/hotspot/jtreg/compiler/c2/TestBit.java +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -1,5 +1,5 @@ @@ -60939,7 +56833,7 @@ index 7805918c28a..823b9f39dbf 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -34,7 +34,7 @@ +@@ -34,7 +34,7 @@ import jdk.test.lib.process.ProcessTools; * * @run driver compiler.c2.TestBit * @@ -60948,7 +56842,7 @@ index 7805918c28a..823b9f39dbf 100644 * @requires vm.debug == true & vm.compiler2.enabled */ public class TestBit { -@@ -54,7 +54,8 @@ static void runTest(String testName) throws Exception { +@@ -54,7 +54,8 @@ public class TestBit { String expectedTestBitInstruction = "ppc64le".equals(System.getProperty("os.arch")) ? "ANDI" : "aarch64".equals(System.getProperty("os.arch")) ? "tb" : @@ -60958,8 +56852,240 @@ index 7805918c28a..823b9f39dbf 100644 if (expectedTestBitInstruction != null) { output.shouldContain(expectedTestBitInstruction); +diff --git a/test/hotspot/jtreg/compiler/calls/TestManyArgs.java b/test/hotspot/jtreg/compiler/calls/TestManyArgs.java +new file mode 100644 +index 0000000000..fbd9c13d7c +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/calls/TestManyArgs.java +@@ -0,0 +1,65 @@ ++/* ++ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2024, Rivos Inc. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++/* @test ++ * @summary Pass values on stack. ++ * @requires os.arch == "riscv64" ++ * @run main/native compiler.calls.TestManyArgs ++ */ ++ ++package compiler.calls; ++ ++public class TestManyArgs { ++ static { ++ System.loadLibrary("TestManyArgs"); ++ } ++ ++ native static void scramblestack(); ++ ++ native static int checkargs(int arg0, short arg1, byte arg2, ++ int arg3, short arg4, byte arg5, ++ int arg6, short arg7, byte arg8, ++ int arg9, short arg10, byte arg11); ++ ++ static int compiledbridge(int arg0, short arg1, byte arg2, ++ int arg3, short arg4, byte arg5, ++ int arg6, short arg7, byte arg8, ++ int arg9, short arg10, byte arg11) { ++ return checkargs(arg0, arg1, arg2, arg3, arg4, arg5, ++ arg6, arg7, arg8, arg9, arg10, arg11); ++ } ++ ++ static public void main(String[] args) { ++ scramblestack(); ++ for (int i = 0; i < 20000; i++) { ++ int res = compiledbridge((int)0xf, (short)0xf, (byte)0xf, ++ (int)0xf, (short)0xf, (byte)0xf, ++ (int)0xf, (short)0xf, (byte)0xf, ++ (int)0xf, (short)0xf, (byte)0xf); ++ if (res != 0) { ++ throw new RuntimeException("Test failed"); ++ } ++ } ++ } ++} +diff --git a/test/hotspot/jtreg/compiler/calls/libTestManyArgs.c b/test/hotspot/jtreg/compiler/calls/libTestManyArgs.c +new file mode 100644 +index 0000000000..8836c79e43 +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/calls/libTestManyArgs.c +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2024, Rivos Inc. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * 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 "jni.h" ++ ++#ifdef riscv64 ++/* RV64 ABI pass all integers as 64-bit, in registers or on stack ++ * As compiler may choose to load smaller width than 64-bit if passed on stack, ++ * this test may not find any bugs. ++ * Therefore we trick the compiler todo 64-bit loads, ++ * by saying these args are jlongs. ++ */ ++JNIEXPORT jint JNICALL Java_compiler_calls_TestManyArgs_checkargs(JNIEnv* env, jclass jclazz, ++ jlong arg0, jlong arg1, jlong arg2, ++ jlong arg3, jlong arg4, jlong arg5, ++ jlong arg6, jlong arg7, jlong arg8, ++ jlong arg9, jlong arg10, jlong arg11) ++#else ++JNIEXPORT jint JNICALL Java_compiler_calls_TestManyArgs_checkargs(JNIEnv* env, jclass jclazz, ++ jint arg0, jshort arg1, jbyte arg2, ++ jint arg3, jshort arg4, jbyte arg5, ++ jint arg6, jshort arg7, jbyte arg8, ++ jint arg9, jshort arg10, jbyte arg11) ++#endif ++{ ++ if (arg0 != 0xf) return 1; ++ if (arg1 != 0xf) return 1; ++ if (arg2 != 0xf) return 1; ++ if (arg3 != 0xf) return 1; ++ if (arg4 != 0xf) return 1; ++ if (arg5 != 0xf) return 1; ++ if (arg6 != 0xf) return 1; ++ if (arg7 != 0xf) return 1; ++ if (arg8 != 0xf) return 1; ++ if (arg9 != 0xf) return 1; ++ if (arg10 != 0xf) return 1; ++ if (arg11 != 0xf) return 1; ++ return 0; ++} ++ ++JNIEXPORT ++void JNICALL Java_compiler_calls_TestManyArgs_scramblestack(JNIEnv* env, jclass jclazz) ++{ ++ volatile char stack[12*8]; ++ for (unsigned int i = 0; i < sizeof(stack); i++) { ++ stack[i] = (char)0xff; ++ } ++} +diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java +new file mode 100644 +index 0000000000..5a1b659bbe +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2022, Alibaba Group Holding Limited. All rights reserved. ++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ++ * ++ * This code is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 only, as ++ * published by the Free Software Foundation. ++ * ++ * This code is distributed in the hope that it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * version 2 for more details (a copy is included in the LICENSE file that ++ * accompanied this code). ++ * ++ * You should have received a copy of the GNU General Public License version ++ * 2 along with this work; if not, write to the Free Software Foundation, ++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ++ * ++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ++ * or visit www.oracle.com if you need additional information or have any ++ * questions. ++ */ ++ ++/* ++ * @test ++ * @summary Test libm intrinsics ++ * @library /test/lib / ++ * ++ * @build sun.hotspot.WhiteBox ++ * @run driver ClassFileInstaller sun.hotspot.WhiteBox ++ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ++ * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement ++ * compiler.floatingpoint.TestLibmIntrinsics ++ */ ++ ++package compiler.floatingpoint; ++ ++import compiler.whitebox.CompilerWhiteBoxTest; ++import sun.hotspot.WhiteBox; ++ ++import java.lang.reflect.Method; ++ ++public class TestLibmIntrinsics { ++ ++ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); ++ ++ private static final double pi = 3.1415926; ++ ++ private static final double expected = 2.5355263553695413; ++ ++ static double m() { ++ return Math.pow(pi, Math.sin(Math.cos(Math.tan(Math.log(Math.log10(Math.exp(pi))))))); ++ } ++ ++ static public void main(String[] args) throws NoSuchMethodException { ++ Method test_method = compiler.floatingpoint.TestLibmIntrinsics.class.getDeclaredMethod("m"); ++ ++ double interpreter_result = m(); ++ ++ // Compile with C1 if possible ++ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); ++ ++ double c1_result = m(); ++ ++ WHITE_BOX.deoptimizeMethod(test_method); ++ ++ // Compile it with C2 if possible ++ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); ++ ++ double c2_result = m(); ++ ++ if (interpreter_result != c1_result || ++ interpreter_result != c2_result || ++ c1_result != c2_result) { ++ System.out.println("interpreter = " + interpreter_result + " c1 = " + c1_result + " c2 = " + c2_result); ++ throw new RuntimeException("Test Failed"); ++ } ++ } ++} diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java -index 558b4218f0b..55374b116e6 100644 +index 558b4218f0..55374b116e 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java @@ -1,5 +1,5 @@ @@ -60969,7 +57095,7 @@ index 558b4218f0b..55374b116e6 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -42,6 +42,7 @@ +@@ -42,6 +42,7 @@ package compiler.intrinsics.sha.cli; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForOtherCPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedAArch64CPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedSparcCPU; @@ -60977,7 +57103,7 @@ index 558b4218f0b..55374b116e6 100644 import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedX86CPU; import compiler.intrinsics.sha.cli.testcases.UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU; -@@ -54,6 +55,8 @@ public static void main(String args[]) throws Throwable { +@@ -54,6 +55,8 @@ public class TestUseSHA1IntrinsicsOptionOnUnsupportedCPU { SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION), new GenericTestCaseForUnsupportedAArch64CPU( SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION), @@ -60987,7 +57113,7 @@ index 558b4218f0b..55374b116e6 100644 SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION), new GenericTestCaseForOtherCPU( diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java -index 3ed72bf0a99..8fb82ee4531 100644 +index 3ed72bf0a9..8fb82ee453 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java @@ -1,5 +1,5 @@ @@ -60997,7 +57123,7 @@ index 3ed72bf0a99..8fb82ee4531 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -42,6 +42,7 @@ +@@ -42,6 +42,7 @@ package compiler.intrinsics.sha.cli; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForOtherCPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedAArch64CPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedSparcCPU; @@ -61005,7 +57131,7 @@ index 3ed72bf0a99..8fb82ee4531 100644 import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedX86CPU; import compiler.intrinsics.sha.cli.testcases.UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU; -@@ -54,6 +55,8 @@ public static void main(String args[]) throws Throwable { +@@ -54,6 +55,8 @@ public class TestUseSHA256IntrinsicsOptionOnUnsupportedCPU { SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION), new GenericTestCaseForUnsupportedAArch64CPU( SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION), @@ -61015,7 +57141,7 @@ index 3ed72bf0a99..8fb82ee4531 100644 SHAOptionsBase.USE_SHA256_INTRINSICS_OPTION), new GenericTestCaseForOtherCPU( diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java -index c05cf309dae..aca32137eda 100644 +index c05cf309da..aca32137ed 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java @@ -1,5 +1,5 @@ @@ -61025,7 +57151,7 @@ index c05cf309dae..aca32137eda 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -42,6 +42,7 @@ +@@ -42,6 +42,7 @@ package compiler.intrinsics.sha.cli; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForOtherCPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedAArch64CPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedSparcCPU; @@ -61033,7 +57159,7 @@ index c05cf309dae..aca32137eda 100644 import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedX86CPU; import compiler.intrinsics.sha.cli.testcases.UseSHAIntrinsicsSpecificTestCaseForUnsupportedCPU; -@@ -54,6 +55,8 @@ public static void main(String args[]) throws Throwable { +@@ -54,6 +55,8 @@ public class TestUseSHA512IntrinsicsOptionOnUnsupportedCPU { SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION), new GenericTestCaseForUnsupportedAArch64CPU( SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION), @@ -61043,7 +57169,7 @@ index c05cf309dae..aca32137eda 100644 SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION), new GenericTestCaseForOtherCPU( diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java -index 58ce5366bae..8deac4f7895 100644 +index 58ce5366ba..8deac4f789 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java @@ -1,5 +1,5 @@ @@ -61053,7 +57179,7 @@ index 58ce5366bae..8deac4f7895 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -41,6 +41,7 @@ +@@ -41,6 +41,7 @@ package compiler.intrinsics.sha.cli; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForOtherCPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedAArch64CPU; import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedSparcCPU; @@ -61061,7 +57187,7 @@ index 58ce5366bae..8deac4f7895 100644 import compiler.intrinsics.sha.cli.testcases.GenericTestCaseForUnsupportedX86CPU; import compiler.intrinsics.sha.cli.testcases.UseSHASpecificTestCaseForUnsupportedCPU; -@@ -53,6 +54,8 @@ public static void main(String args[]) throws Throwable { +@@ -53,6 +54,8 @@ public class TestUseSHAOptionOnUnsupportedCPU { SHAOptionsBase.USE_SHA_OPTION), new GenericTestCaseForUnsupportedAArch64CPU( SHAOptionsBase.USE_SHA_OPTION), @@ -61071,7 +57197,7 @@ index 58ce5366bae..8deac4f7895 100644 SHAOptionsBase.USE_SHA_OPTION), new GenericTestCaseForOtherCPU( diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java -index faa9fdbae67..26635002040 100644 +index faa9fdbae6..2663500204 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java @@ -1,5 +1,5 @@ @@ -61081,7 +57207,7 @@ index faa9fdbae67..26635002040 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -32,26 +32,27 @@ +@@ -32,26 +32,27 @@ import jdk.test.lib.cli.predicate.OrPredicate; /** * Generic test case for SHA-related options targeted to any CPU except @@ -61115,7 +57241,7 @@ index faa9fdbae67..26635002040 100644 new String[] { ".*" + optionName + ".*" }, shouldPassMessage, diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java new file mode 100644 -index 00000000000..2ecfec07a4c +index 0000000000..8566d57c39 --- /dev/null +++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java @@ -0,0 +1,115 @@ @@ -61145,7 +57271,7 @@ index 00000000000..2ecfec07a4c + +package compiler.intrinsics.sha.cli.testcases; + -+import compiler.intrinsics.sha.cli.DigestOptionsBase; ++import compiler.intrinsics.sha.cli.SHAOptionsBase; +import jdk.test.lib.process.ExitCode; +import jdk.test.lib.Platform; +import jdk.test.lib.cli.CommandLineOptionTest; @@ -61157,7 +57283,7 @@ index 00000000000..2ecfec07a4c + * which don't support instruction required by the tested option. + */ +public class GenericTestCaseForUnsupportedRISCV64CPU extends -+ DigestOptionsBase.TestCase { ++ SHAOptionsBase.TestCase { + + final private boolean checkUseSHA; + @@ -61167,7 +57293,7 @@ index 00000000000..2ecfec07a4c + + public GenericTestCaseForUnsupportedRISCV64CPU(String optionName, boolean checkUseSHA) { + super(optionName, new AndPredicate(Platform::isRISCV64, -+ new NotPredicate(DigestOptionsBase.getPredicateForOption( ++ new NotPredicate(SHAOptionsBase.getPredicateForOption( + optionName)))); + + this.checkUseSHA = checkUseSHA; @@ -61179,27 +57305,27 @@ index 00000000000..2ecfec07a4c + + "option '-XX:-%s' without any warnings", optionName); + //Verify that option could be disabled without any warnings. + CommandLineOptionTest.verifySameJVMStartup(null, new String[] { -+ DigestOptionsBase.getWarningForUnsupportedCPU(optionName) ++ SHAOptionsBase.getWarningForUnsupportedCPU(optionName) + }, shouldPassMessage, shouldPassMessage, ExitCode.OK, -+ DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, ++ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.prepareBooleanFlag(optionName, false)); + + if (checkUseSHA) { + shouldPassMessage = String.format("If JVM is started with '-XX:-" + + "%s' '-XX:+%s', output should contain warning.", -+ DigestOptionsBase.USE_SHA_OPTION, optionName); ++ SHAOptionsBase.USE_SHA_OPTION, optionName); + + // Verify that when the tested option is enabled, then + // a warning will occur in VM output if UseSHA is disabled. -+ if (!optionName.equals(DigestOptionsBase.USE_SHA_OPTION)) { ++ if (!optionName.equals(SHAOptionsBase.USE_SHA_OPTION)) { + CommandLineOptionTest.verifySameJVMStartup( -+ new String[] { DigestOptionsBase.getWarningForUnsupportedCPU(optionName) }, ++ new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, + null, + shouldPassMessage, + shouldPassMessage, + ExitCode.OK, -+ DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -+ CommandLineOptionTest.prepareBooleanFlag(DigestOptionsBase.USE_SHA_OPTION, false), ++ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, ++ CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false), + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + } + } @@ -61211,7 +57337,7 @@ index 00000000000..2ecfec07a4c + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be disabled by default", + optionName), -+ DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS); ++ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS); + + if (checkUseSHA) { + // Verify that option is disabled even if it was explicitly enabled @@ -61219,7 +57345,7 @@ index 00000000000..2ecfec07a4c + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "RISCV64CPU even if set to true directly", optionName), -+ DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, ++ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + + // Verify that option is disabled when +UseSHA was passed to JVM. @@ -61227,15 +57353,15 @@ index 00000000000..2ecfec07a4c + String.format("Option '%s' should be off on unsupported " + + "RISCV64CPU even if %s flag set to JVM", + optionName, CommandLineOptionTest.prepareBooleanFlag( -+ DigestOptionsBase.USE_SHA_OPTION, true)), -+ DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, ++ SHAOptionsBase.USE_SHA_OPTION, true)), ++ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, + CommandLineOptionTest.prepareBooleanFlag( -+ DigestOptionsBase.USE_SHA_OPTION, true)); ++ SHAOptionsBase.USE_SHA_OPTION, true)); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Double.java b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Double.java -index 2e3e2717a65..7be8af6d035 100644 +index 2e3e2717a6..7be8af6d03 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Double.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Double.java @@ -1,5 +1,5 @@ @@ -61255,7 +57381,7 @@ index 2e3e2717a65..7be8af6d035 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Float.java b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Float.java -index 0e06a9e4327..797927b42bf 100644 +index 0e06a9e432..797927b42b 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Float.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Float.java @@ -1,5 +1,5 @@ @@ -61275,7 +57401,7 @@ index 0e06a9e4327..797927b42bf 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Int.java b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Int.java -index c3cdbf37464..be8f7d586c2 100644 +index c3cdbf3746..be8f7d586c 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Int.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/ProdRed_Int.java @@ -1,5 +1,5 @@ @@ -61295,7 +57421,7 @@ index c3cdbf37464..be8f7d586c2 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java b/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java -index d33bd411f16..d96d5e29c00 100644 +index d33bd411f1..d96d5e29c0 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java @@ -1,5 +1,5 @@ @@ -61315,7 +57441,7 @@ index d33bd411f16..d96d5e29c00 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions * -XX:LoopUnrollLimit=250 -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Double.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Double.java -index 992fa4b5161..b09c873d05d 100644 +index 992fa4b516..b09c873d05 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Double.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Double.java @@ -1,5 +1,5 @@ @@ -61335,7 +57461,7 @@ index 992fa4b5161..b09c873d05d 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Float.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Float.java -index 3e79b3528b7..fe40ed6f98d 100644 +index 3e79b3528b..fe40ed6f98 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Float.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedAbsNeg_Float.java @@ -1,5 +1,5 @@ @@ -61355,7 +57481,7 @@ index 3e79b3528b7..fe40ed6f98d 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedSqrt_Double.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedSqrt_Double.java -index 6603dd224ef..51631910493 100644 +index 6603dd224e..5163191049 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRedSqrt_Double.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRedSqrt_Double.java @@ -1,5 +1,5 @@ @@ -61375,7 +57501,7 @@ index 6603dd224ef..51631910493 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Double.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Double.java -index d9a0c988004..d999ae423cf 100644 +index d9a0c98800..d999ae423c 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Double.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Double.java @@ -1,5 +1,5 @@ @@ -61395,7 +57521,7 @@ index d9a0c988004..d999ae423cf 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Float.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Float.java -index 722db95aed3..65912a5c7fa 100644 +index 722db95aed..65912a5c7f 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Float.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Float.java @@ -1,5 +1,5 @@ @@ -61415,7 +57541,7 @@ index 722db95aed3..65912a5c7fa 100644 * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Int.java b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Int.java -index f58f21feb23..fffdc2f7565 100644 +index f58f21feb2..fffdc2f756 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Int.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/SumRed_Int.java @@ -1,5 +1,5 @@ @@ -61434,8 +57560,34 @@ index f58f21feb23..fffdc2f7565 100644 * * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:LoopUnrollLimit=250 * -XX:CompileThresholdScaling=0.1 +diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java +index acb86812d2..2c866f26f0 100644 +--- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java ++++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java +@@ -24,7 +24,7 @@ + + /* @test + * @bug 8167409 +- * @requires (os.arch != "aarch64") & (os.arch != "arm") ++ * @requires (os.arch != "aarch64") & (os.arch != "riscv64") & (os.arch != "arm") + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs + */ + package compiler.runtime.criticalnatives.argumentcorruption; +diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java +index eab36f9311..1da369fde2 100644 +--- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java ++++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java +@@ -24,7 +24,7 @@ + + /* @test + * @bug 8167408 +- * @requires (os.arch != "aarch64") & (os.arch != "arm") ++ * @requires (os.arch != "aarch64") & (os.arch != "riscv64") & (os.arch != "arm") + * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.lookup.LookUp + */ + package compiler.runtime.criticalnatives.lookup; diff --git a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java -index 7774dabcb5f..7afe3560f30 100644 +index 7774dabcb5..7afe3560f3 100644 --- a/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java +++ b/test/hotspot/jtreg/compiler/testlibrary/sha/predicate/IntrinsicPredicates.java @@ -1,5 +1,5 @@ @@ -61486,8 +57638,84 @@ index 7774dabcb5f..7afe3560f30 100644 public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE, +diff --git a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java +index 5aea51a24f..da63e02555 100644 +--- a/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java ++++ b/test/hotspot/jtreg/gc/stress/TestStressG1Humongous.java +@@ -24,14 +24,41 @@ + package gc.stress; + + /* +- * @test TestStressG1Humongous ++ * @test + * @key gc stress + * @summary Stress G1 by humongous allocations in situation near OOM + * @requires vm.gc.G1 + * @requires !vm.flightRecorder + * @library /test/lib + * @modules java.base/jdk.internal.misc +- * @run driver/timeout=1300 gc.stress.TestStressG1Humongous ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 4 3 1.1 120 ++ */ ++ ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 16 5 2.1 120 ++ */ ++ ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=180 gc.stress.TestStressG1Humongous 32 4 0.6 120 ++ */ ++ ++/* ++ * @test ++ * @requires vm.gc.G1 ++ * @requires !vm.flightRecorder ++ * @library /test/lib ++ * @modules java.base/jdk.internal.misc ++ * @run driver/timeout=900 gc.stress.TestStressG1Humongous 1 7 0.6 600 + */ + + import java.util.ArrayList; +@@ -48,17 +75,19 @@ import jdk.test.lib.process.OutputAnalyzer; + public class TestStressG1Humongous{ + + public static void main(String[] args) throws Exception { ++ if (args.length != 4) { ++ throw new IllegalArgumentException("Test expects 4 arguments"); ++ } ++ + // Limit heap size on 32-bit platforms + int heapSize = Platform.is32bit() ? 512 : 1024; +- // Heap size, region size, threads, humongous size, timeout +- run(heapSize, 4, 3, 1.1, 120); +- run(heapSize, 16, 5, 2.1, 120); +- run(heapSize, 32, 4, 0.6, 120); +- run(heapSize, 1, 7, 0.6, 600); +- } + +- private static void run(int heapSize, int regionSize, int threads, double humongousSize, int timeout) +- throws Exception { ++ // Region size, threads, humongous size, and timeout passed as @run arguments ++ int regionSize = Integer.parseInt(args[0]); ++ int threads = Integer.parseInt(args[1]); ++ double humongousSize = Double.parseDouble(args[2]); ++ int timeout = Integer.parseInt(args[3]); ++ + ArrayList options = new ArrayList<>(); + Collections.addAll(options, Utils.getTestJavaOpts()); + Collections.addAll(options, diff --git a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java -index 57256aa5a32..d4d43b01ae6 100644 +index 57256aa5a3..d4d43b01ae 100644 --- a/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java +++ b/test/hotspot/jtreg/runtime/NMT/CheckForProperDetailStackTrace.java @@ -1,5 +1,5 @@ @@ -61497,7 +57725,7 @@ index 57256aa5a32..d4d43b01ae6 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -112,7 +112,7 @@ public static void main(String args[]) throws Exception { +@@ -112,7 +112,7 @@ public class CheckForProperDetailStackTrace { // It's ok for ARM not to have symbols, because it does not support NMT detail // when targeting thumb2. It's also ok for Windows not to have symbols, because // they are only available if the symbols file is included with the build. @@ -61507,7 +57735,7 @@ index 57256aa5a32..d4d43b01ae6 100644 } output.reportDiagnosticSummary(); diff --git a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java -index 127bb6abcd9..eab19273ad8 100644 +index 127bb6abcd..eab19273ad 100644 --- a/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java +++ b/test/hotspot/jtreg/runtime/ReservedStack/ReservedStackTest.java @@ -1,5 +1,5 @@ @@ -61517,7 +57745,7 @@ index 127bb6abcd9..eab19273ad8 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -239,7 +239,7 @@ private static boolean isAlwaysSupportedPlatform() { +@@ -239,7 +239,7 @@ public class ReservedStackTest { return Platform.isAix() || (Platform.isLinux() && (Platform.isPPC() || Platform.isS390x() || Platform.isX64() || @@ -61526,21 +57754,11 @@ index 127bb6abcd9..eab19273ad8 100644 Platform.isOSX() || Platform.isSolaris(); } -diff --git a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -index 54640b245f8..f0b7aed5ceb 100644 ---- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -@@ -1,5 +1,4 @@ - /* -- * Copyright (c) 2018, Google 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 diff --git a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java -index 77458554b76..d4bfe31dd7a 100644 +index 126a43a900..feb4de5388 100644 --- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java -@@ -45,7 +45,7 @@ +@@ -45,7 +45,7 @@ import java.util.Set; */ public class TestMutuallyExclusivePlatformPredicates { private static enum MethodGroup { @@ -61549,8 +57767,622 @@ index 77458554b76..d4bfe31dd7a 100644 BITNESS("is32bit", "is64bit"), OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"), VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"), +diff --git a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html +deleted file mode 100644 +index 7049e82703..0000000000 +--- a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.html ++++ /dev/null +@@ -1,43 +0,0 @@ +- +- +- +- +- +- ManualYesNoTest +- +- +- +-

ManualYesNoTest
Bug ID:

+- +-

See the dialog box (usually in upper left corner) for instructions

+- +- +- +- +diff --git a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java +index 8b509a1231..446b7a3a93 100644 +--- a/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java ++++ b/test/jdk/java/awt/List/MouseDraggedOutCauseScrollingTest/MouseDraggedOutCauseScrollingTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -22,29 +22,29 @@ + */ + + /* +- test ++ @test + @bug 6243382 8006070 + @summary Dragging of mouse outside of a List and Choice area don't work properly on XAWT +- @author Dmitry.Cherepanov@SUN.COM area=awt.list +- @run applet/manual=yesno MouseDraggedOutCauseScrollingTest.html ++ @requires (os.family == "linux") ++ @library /java/awt/regtesthelpers ++ @run main/manual MouseDraggedOutCauseScrollingTest + */ + +-import java.applet.Applet; +-import java.awt.*; ++import java.awt.Choice; ++import java.awt.Frame; ++import java.awt.GridLayout; ++import java.awt.List; ++import java.awt.Toolkit; + +-public class MouseDraggedOutCauseScrollingTest extends Applet +-{ +- Choice choice; +- List singleList; +- List multipleList; ++public class MouseDraggedOutCauseScrollingTest { + +- public void init() +- { +- this.setLayout (new GridLayout (1, 3)); ++ static Frame createUI() { ++ Frame frame = new Frame("MouseDraggedOutCausesScrollingTest"); ++ frame.setLayout(new GridLayout(1, 3)); + +- choice = new Choice(); +- singleList = new List(3, false); +- multipleList = new List(3, true); ++ Choice choice = new Choice(); ++ List singleList = new List(3, false); ++ List multipleList = new List(3, true); + + choice.add("Choice"); + for (int i = 1; i < 100; i++){ +@@ -59,188 +59,66 @@ public class MouseDraggedOutCauseScrollingTest extends Applet + for (int i = 1; i < 100; i++) + multipleList.add(""+i); + +- this.add(choice); +- this.add(singleList); +- this.add(multipleList); ++ frame.add(choice); ++ frame.add(singleList); ++ frame.add(multipleList); ++ frame.setSize(400, 100); ++ return frame; ++ } + ++ public static void main(String[] args) throws Exception { + String toolkitName = Toolkit.getDefaultToolkit().getClass().getName(); ++ + if (!toolkitName.equals("sun.awt.X11.XToolkit")) { +- String[] instructions = +- { +- "This test is not applicable to the current platform. Press PASS" +- }; +- Sysout.createDialogWithInstructions( instructions ); +- } else { +- String[] instructions = +- { +- "0) Please note, that this is only Motif/XAWT test. At first, make the applet active", +- "1.1) Click on the choice", +- "1.2) Press the left button of the mouse and keep on any item of the choice, for example 5", +- "1.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "1.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", +- "1.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", +- "-----------------------------------", +- "2.1) Click on the single list", +- "2.2) Press the left button of the mouse and keep on any item of the list, for example 5", +- "2.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "2.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling UP of the list and selected item changes on the upper. If not, the test failed", +- "2.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling DOWN of the list and selected item changes on the lower. If not, the test failed", +- "-----------------------------------", +- "3.1) Click on the multiple list", +- "3.2) Press the left button of the mouse and keep on any item of the list, for example 5", +- "3.3) Drag mouse out of the area of the unfurled list, at the same time hold the X coordinate of the mouse position about the same", +- "3.4) To make sure, that when the Y coordinate of the mouse position higher of the upper bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the upper. If not, the test failed", +- "3.5) To make sure, that when the Y coordinate of the mouse position under of the lower bound of the list then scrolling of the list NO OCCURED and selected item NO CHANGES on the lower. If not, the test failed", +- "4) Test passed." +- }; +- Sysout.createDialogWithInstructions( instructions ); ++ System.out.println(INAPPLICABLE); ++ return; + } + +- }//End init() +- +- public void start () +- { +- setSize (400,100); +- setVisible(true); +- validate(); +- +- }// start() +- +-}// class ManualYesNoTest +- +-/**************************************************** +- Standard Test Machinery +- DO NOT modify anything below -- it's a standard +- chunk of code whose purpose is to make user +- interaction uniform, and thereby make it simpler +- to read and understand someone else's test. +- ****************************************************/ +- +-/** +- This is part of the standard test machinery. +- It creates a dialog (with the instructions), and is the interface +- for sending text messages to the user. +- To print the instructions, send an array of strings to Sysout.createDialog +- WithInstructions method. Put one line of instructions per array entry. +- To display a message for the tester to see, simply call Sysout.println +- with the string to be displayed. +- This mimics System.out.println but works within the test harness as well +- as standalone. +- */ +- +-class Sysout +-{ +- private static TestDialog dialog; +- +- public static void createDialogWithInstructions( String[] instructions ) +- { +- dialog = new TestDialog( new Frame(), "Instructions" ); +- dialog.printInstructions( instructions ); +- dialog.setVisible(true); +- println( "Any messages for the tester will display here." ); +- } +- +- public static void createDialog( ) +- { +- dialog = new TestDialog( new Frame(), "Instructions" ); +- String[] defInstr = { "Instructions will appear here. ", "" } ; +- dialog.printInstructions( defInstr ); +- dialog.setVisible(true); +- println( "Any messages for the tester will display here." ); +- } +- +- +- public static void printInstructions( String[] instructions ) +- { +- dialog.printInstructions( instructions ); +- } +- +- +- public static void println( String messageIn ) +- { +- dialog.displayMessage( messageIn ); +- } +- +-}// Sysout class +- +-/** +- This is part of the standard test machinery. It provides a place for the +- test instructions to be displayed, and a place for interactive messages +- to the user to be displayed. +- To have the test instructions displayed, see Sysout. +- To have a message to the user be displayed, see Sysout. +- Do not call anything in this dialog directly. +- */ +-class TestDialog extends Dialog +-{ +- +- TextArea instructionsText; +- TextArea messageText; +- int maxStringLength = 80; +- +- //DO NOT call this directly, go through Sysout +- public TestDialog( Frame frame, String name ) +- { +- super( frame, name ); +- int scrollBoth = TextArea.SCROLLBARS_BOTH; +- instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); +- add( "North", instructionsText ); +- +- messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); +- add("Center", messageText); +- +- pack(); +- +- setVisible(true); +- }// TestDialog() +- +- //DO NOT call this directly, go through Sysout +- public void printInstructions( String[] instructions ) +- { +- //Clear out any current instructions +- instructionsText.setText( "" ); +- +- //Go down array of instruction strings +- +- String printStr, remainingStr; +- for( int i=0; i < instructions.length; i++ ) +- { +- //chop up each into pieces maxSringLength long +- remainingStr = instructions[ i ]; +- while( remainingStr.length() > 0 ) +- { +- //if longer than max then chop off first max chars to print +- if( remainingStr.length() >= maxStringLength ) +- { +- //Try to chop on a word boundary +- int posOfSpace = remainingStr. +- lastIndexOf( ' ', maxStringLength - 1 ); +- +- if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; +- +- printStr = remainingStr.substring( 0, posOfSpace + 1 ); +- remainingStr = remainingStr.substring( posOfSpace + 1 ); +- } +- //else just print +- else +- { +- printStr = remainingStr; +- remainingStr = ""; +- } +- +- instructionsText.append( printStr + "\n" ); +- +- }// while +- +- }// for +- +- }//printInstructions() +- +- //DO NOT call this directly, go through Sysout +- public void displayMessage( String messageIn ) +- { +- messageText.append( messageIn + "\n" ); +- System.out.println(messageIn); ++ PassFailJFrame ++ .builder() ++ .instructions(INSTRUCTIONS) ++ .rows(40) ++ .columns(70) ++ .testUI(MouseDraggedOutCauseScrollingTest::createUI) ++ .build() ++ .awaitAndCheck(); + } + +-}// TestDialog class ++ static final String INAPPLICABLE = "The test is not applicable to the current platform. Test PASSES."; ++ static final String INSTRUCTIONS = "0) Please note, that this is an XAWT/Linux only test. First, make the test window is active.\n" + ++ "-----------------------------------\n" + ++ "1.1) Click on the Choice.\n" + ++ "1.2) Press and hold down the left button of the mouse to select (eg) item 5 in the choice.\n" + ++ "1.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "1.4) Check that when the Y coordinate of the mouse position is higher than the upper bound of the list\n" + ++ " then the list continues to scrolls UP and the selected item changes at the top until you reach the topmost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "1.5) Check that when the Y coordinate of the mouse position is lower than the lower bound of the list\n" + ++ " then the list continues to scroll DOWN and the selected item changes at the bottom until you reach the bottommost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "2.1) Click on the Single List.\n" + ++ "2.2) Press and hold down the left button of the mouse to select (eg) item 5 in the list.\n" + ++ "2.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "2.4) Check that when the Y coordinate of the mouse position is higher than the upper bound of the list\n" + ++ " then the list continues to scrolls UP and the selected item changes at the top until you reach the topmost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "2.5) Check that when the Y coordinate of the mouse position is lower than the lower bound of the list\n" + ++ " then the list continues to scroll DOWN and the selected item changes at the bottom until you reach the bottommost item.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "3.1) Click on the Multiple List.\n" + ++ "3.2) Press and hold down the left button of the mouse to select (eg) item 5 in the list.\n" + ++ "3.3) Drag the mouse vertically out of the area of the open list,\n" + ++ " keeping the X coordinate of the mouse position about the same.\n" + ++ "3.4) Check that when the Y coordinate of the mouse is higher than the upper bound of the list\n" + ++ " that scrolling of the list DOES NOT OCCUR and the selected item IS UNCHANGED at the top.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "3.5) Check that when the Y coordinate of the mouse is below the lower bound of the list\n" + ++ " that scrolling of the list DOES NOT OCCUR and the selected item IS UNCHANGED at the bottom.\n" + ++ " If not, the test failed. Press FAIL.\n" + ++ "-----------------------------------\n" + ++ "4) The test has now passed. Press PASS."; ++} +diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html +index a562b886ab..e69de29bb2 100644 +--- a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html ++++ b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.html +@@ -1,44 +0,0 @@ +- +- +- +- +- PrintDialogsTest +- +- +- +- +-Please select dialog modality type and parent; also select +-the print auxiliary dialog to be displayed (Page Setup or Print dialog). +-Then click "Start test" button. +- +-When the windows will appear check if modal blocking for Dialog works as expected. +-Then push "Open" button on the Dialog to show the auxiliary dialog and check +-if it blocks the rest of the application. Then close it and check correctness +-of modal blocking behavior for the Dialog again. To close all the test +-windows please push "Finish" button. +- +-To finish the overall test push "Pass" or "Fail" button depending on result. +- +- +- +diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java +index 989c48295b..8a07d284a9 100644 +--- a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java ++++ b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -25,21 +25,75 @@ + /* + * @test + * @bug 8055836 8057694 8055752 +- * @summary Check if Print and Page Setup dialogs lock other windows; ++ * @summary Check if Print and Page Setup dialogs block other windows; + * check also correctness of modal behavior for other dialogs. +- * +- * @run applet/manual=yesno PrintDialogsTest.html ++ * @library /java/awt/regtesthelpers ++ * @run main/manual PrintDialogsTest + */ + + +-import java.applet.Applet; +-import java.awt.*; ++import java.awt.BorderLayout; ++import java.awt.Button; ++import java.awt.Checkbox; ++import java.awt.CheckboxGroup; ++import java.awt.Dialog; ++import java.awt.Frame; ++import java.awt.EventQueue; ++import java.awt.GridLayout; ++import java.awt.Label; ++import java.awt.Panel; + + import java.awt.event.ActionEvent; + import java.awt.event.ActionListener; + + +-public class PrintDialogsTest extends Applet implements ActionListener { ++public class PrintDialogsTest extends Panel implements ActionListener { ++ ++ static final String INSTRUCTIONS = ++ "This test is free format, which means there is no enforced or guided sequence." + "\n" + ++ ++ "Please select each of " + "\n" + ++ "(a) The dialog parent type." + "\n" + ++ "(b) The dialog modality type" + "\n" + ++ "(c) The print dialog type (Print dialog or Page Setup dialog)" + "\n" + ++ ++ "Once the choices have been made click the \"Start test\" button." + "\n" + ++ ++ "Three windows will appear" + "\n" + ++ "(1) A Frame or a Dialog - in the case you selected \"Dialog\" as the parent type" + "\n" + ++ "(2) a Window (ie an undecorated top-level)" + "\n" + ++ "(3) A dialog with two buttons \"Open\" and \"Finish\"" + "\n" + ++ ++ "Now check as follows whether modal blocking works as expected." + "\n" + ++ "Windows (1) and (2) contain a button which you should be able to press" + "\n" + ++ "ONLY if you selected \"Non-modal\", or \"Modeless\" for modality type." + "\n" + ++ "In other cases window (3) will block input to (1) and (2)" + "\n" + ++ ++ "Then push the \"Open\" button on the Dialog to show the printing dialog and check" + "\n" + ++ "if it blocks the rest of the application - ie all of windows (1), (2) and (3)" + "\n" + ++ "should ALWAYS be blocked when the print dialog is showing." + "\n" + ++ "Now cancel the printing dialog and check the correctness of modal blocking" + "\n" + ++ "behavior for the Dialog again." + "\n" + ++ "To close all the 3 test windows please push the \"Finish\" button." + "\n" + ++ ++ "Repeat all the above for different combinations, which should include" + "\n" + ++ "using all of the Dialog parent choices and all of the Dialog Modality types." + "\n" + ++ ++ "If any behave incorrectly, note the combination of choices and press Fail." + "\n" + ++ ++ "If all behave correctly, press Pass."; ++ ++ public static void main(String[] args) throws Exception { ++ ++ PassFailJFrame.builder() ++ .instructions(INSTRUCTIONS) ++ .rows(35) ++ .columns(60) ++ .testUI(PrintDialogsTest::createUI) ++ .testTimeOut(10) ++ .build() ++ .awaitAndCheck(); ++ } + + private Button btnTest; + private Checkbox cbPage, cbPrint, +@@ -48,6 +102,14 @@ public class PrintDialogsTest extends Applet implements ActionListener { + + private CheckboxGroup groupDialog, groupParent, groupModType; + ++ private static Frame createUI() { ++ Frame frame = new Frame("Dialog Modality Testing"); ++ PrintDialogsTest test = new PrintDialogsTest(); ++ test.createGUI(); ++ frame.add(test); ++ frame.pack(); ++ return frame; ++ } + + public void actionPerformed(ActionEvent e) { + +@@ -99,13 +161,13 @@ public class PrintDialogsTest extends Applet implements ActionListener { + + setLayout(new BorderLayout()); + +- setSize(350, 200); + Panel panel = new Panel(); +- panel.setLayout(new GridLayout(18, 1)); ++ panel.setLayout(new GridLayout(21, 1)); + + btnTest = new Button("Start test"); + btnTest.addActionListener(this); + panel.add(btnTest); ++ panel.add(new Label(" ")); // spacing + + + panel.add(new Label("Dialog parent:")); +@@ -123,6 +185,7 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbHiddFrm); + panel.add(cbDlg); + panel.add(cbFrm); ++ panel.add(new Label(" ")); // spacing + + panel.add(new Label("Dialog modality type:")); + groupModType = new CheckboxGroup(); +@@ -139,7 +202,7 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbDocModal); + panel.add(cbTKModal); + panel.add(cbModeless); +- add(panel); ++ panel.add(new Label(" ")); // spacing + + panel.add(new Label("Print dialog type:")); + groupDialog = new CheckboxGroup(); +@@ -148,13 +211,6 @@ public class PrintDialogsTest extends Applet implements ActionListener { + panel.add(cbPage); + panel.add(cbPrint); + +- validate(); +- setVisible(true); +- } +- +- public void start() { +- try { +- EventQueue.invokeAndWait(this::createGUI); +- } catch (Exception e) {} ++ add(panel); + } + } +diff --git a/test/jdk/javax/naming/module/RunBasic.java b/test/jdk/javax/naming/module/RunBasic.java +index 512062de40..f9d259d620 100644 +--- a/test/jdk/javax/naming/module/RunBasic.java ++++ b/test/jdk/javax/naming/module/RunBasic.java +@@ -134,7 +134,15 @@ public class RunBasic { + opts.add("test/" + clsName); + opts.add("ldap://" + HOST_NAME + "/dc=ie,dc=oracle,dc=com"); + System.out.println("Running with the '" + desc + "' module..."); ++<<<<<<< HEAD ++ runJava("-Dtest.src=" + TEST_SRC, "-p", "mods", "-m", "test/" + clsName, ++ "ldap://" + HOST_NAME + "/dc=ie,dc=oracle,dc=com"); ++||||||| 82c330b464 ++ runJava("-Dtest.src=" + TEST_SRC, "-p", "mods", "-m", "test/" + clsName, ++ "ldap://localhost/dc=ie,dc=oracle,dc=com"); ++======= + runJava(opts.toArray(String[]::new)); ++>>>>>>> cee8535a9d3de8558b4b5028d68e397e508bef71 + } + + private static void runJava(String... opts) throws Throwable { +diff --git a/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java b/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java +index a275eda517..2cb092e60b 100644 +--- a/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java ++++ b/test/jdk/jdk/jfr/event/oldobject/TestListenerLeak.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2018, 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 +@@ -74,15 +74,17 @@ public class TestListenerLeak { + + public static void main(String[] args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); +- +- try (Recording r = new Recording()) { +- r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); +- r.start(); +- listenerLeak(); +- r.stop(); +- List events = Events.fromRecording(r); +- if (OldObjects.countMatchingEvents(events, Stuff[].class, null, null, -1, "listenerLeak") == 0) { +- throw new Exception("Could not find leak with " + Stuff[].class); ++ while (true) { ++ try (Recording r = new Recording()) { ++ r.enable(EventNames.OldObjectSample).withStackTrace().with("cutoff", "infinity"); ++ r.start(); ++ listenerLeak(); ++ r.stop(); ++ List events = Events.fromRecording(r); ++ if (OldObjects.countMatchingEvents(events, Stuff[].class, null, null, -1, "listenerLeak") != 0) { ++ return; // Success ++ } ++ System.out.println("Could not find leak with " + Stuff[].class + ". Retrying."); + } + } + } diff --git a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java b/test/jdk/jdk/jfr/event/os/TestCPUInformation.java -index 7990c49a1f6..abeff80e5e8 100644 +index 7990c49a1f..abeff80e5e 100644 --- a/test/jdk/jdk/jfr/event/os/TestCPUInformation.java +++ b/test/jdk/jdk/jfr/event/os/TestCPUInformation.java @@ -1,5 +1,5 @@ @@ -61560,7 +58392,7 @@ index 7990c49a1f6..abeff80e5e8 100644 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it -@@ -54,8 +54,8 @@ public static void main(String[] args) throws Throwable { +@@ -54,8 +54,8 @@ public class TestCPUInformation { Events.assertField(event, "hwThreads").atLeast(1); Events.assertField(event, "cores").atLeast(1); Events.assertField(event, "sockets").atLeast(1); @@ -61571,11 +58403,142 @@ index 7990c49a1f6..abeff80e5e8 100644 } } } +diff --git a/test/jdk/sun/util/calendar/zi/Month.java b/test/jdk/sun/util/calendar/zi/Month.java +index cb60b8d441..bab909f763 100644 +--- a/test/jdk/sun/util/calendar/zi/Month.java ++++ b/test/jdk/sun/util/calendar/zi/Month.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -21,11 +21,6 @@ + * questions. + */ + +-import java.util.ArrayList; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; +- + /** + * Month enum handles month related manipulation. + * +@@ -47,15 +42,6 @@ enum Month { + + private final String abbr; + +- private static final Map abbreviations +- = new HashMap(12); +- +- static { +- for (Month m : Month.values()) { +- abbreviations.put(m.abbr, m); +- } +- } +- + private Month(String abbr) { + this.abbr = abbr; + } +@@ -70,11 +56,22 @@ enum Month { + * @return the Month value + */ + static Month parse(String name) { +- Month m = abbreviations.get(name); +- if (m != null) { +- return m; +- } +- return null; ++ int len = name.length(); ++ ++ if (name.regionMatches(true, 0, "January", 0, len)) return Month.JANUARY; ++ if (name.regionMatches(true, 0, "February", 0, len)) return Month.FEBRUARY; ++ if (name.regionMatches(true, 0, "March", 0, len)) return Month.MARCH; ++ if (name.regionMatches(true, 0, "April", 0, len)) return Month.APRIL; ++ if (name.regionMatches(true, 0, "May", 0, len)) return Month.MAY; ++ if (name.regionMatches(true, 0, "June", 0, len)) return Month.JUNE; ++ if (name.regionMatches(true, 0, "July", 0, len)) return Month.JULY; ++ if (name.regionMatches(true, 0, "August", 0, len)) return Month.AUGUST; ++ if (name.regionMatches(true, 0, "September", 0, len)) return Month.SEPTEMBER; ++ if (name.regionMatches(true, 0, "October", 0, len)) return Month.OCTOBER; ++ if (name.regionMatches(true, 0, "November", 0, len)) return Month.NOVEMBER; ++ if (name.regionMatches(true, 0, "December", 0, len)) return Month.DECEMBER; ++ ++ throw new IllegalArgumentException("Unknown month: " + name); + } + + /** +diff --git a/test/jdk/sun/util/calendar/zi/RuleDay.java b/test/jdk/sun/util/calendar/zi/RuleDay.java +index bc730944b4..9cd81c1e52 100644 +--- a/test/jdk/sun/util/calendar/zi/RuleDay.java ++++ b/test/jdk/sun/util/calendar/zi/RuleDay.java +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. ++ * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it +@@ -21,11 +21,6 @@ + * questions. + */ + +-import java.util.ArrayList; +-import java.util.HashMap; +-import java.util.List; +-import java.util.Map; +- + /** + * RuleDay class represents the value of the "ON" field. The day of + * week values start from 1 following the {@link java.util.Calendar} +@@ -34,13 +29,6 @@ import java.util.Map; + * @since 1.4 + */ + class RuleDay { +- private static final Map abbreviations = new HashMap(7); +- static { +- for (DayOfWeek day : DayOfWeek.values()) { +- abbreviations.put(day.getAbbr(), day); +- } +- } +- + private String dayName = null; + private DayOfWeek dow; + private boolean lastOne = false; +@@ -166,13 +154,23 @@ class RuleDay { + return sign + toString(d); + } + +- private static DayOfWeek getDOW(String abbr) { +- return abbreviations.get(abbr); ++ private static DayOfWeek getDOW(String name) { ++ int len = name.length(); ++ ++ if (name.regionMatches(true, 0, "Monday", 0, len)) return DayOfWeek.MONDAY; ++ if (name.regionMatches(true, 0, "Tuesday", 0, len)) return DayOfWeek.TUESDAY; ++ if (name.regionMatches(true, 0, "Wednesday", 0, len)) return DayOfWeek.WEDNESDAY; ++ if (name.regionMatches(true, 0, "Thursday", 0, len)) return DayOfWeek.THURSDAY; ++ if (name.regionMatches(true, 0, "Friday", 0, len)) return DayOfWeek.FRIDAY; ++ if (name.regionMatches(true, 0, "Saturday", 0, len)) return DayOfWeek.SATURDAY; ++ if (name.regionMatches(true, 0, "Sunday", 0, len)) return DayOfWeek.SUNDAY; ++ ++ throw new IllegalArgumentException("Unknown day-of-week: " + name); + } + + /** + * Converts the specified day of week value to the day-of-week +- * name defined in {@link java.util.Calenda}. ++ * name defined in {@link java.util.Calendar}. + * @param dow 1-based day of week value + * @return the Calendar day of week name with "Calendar." prefix. + * @throws IllegalArgumentException if the specified dow value is out of range. diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java -index f4ee0546c70..635cdd18054 100644 +index 6269373c2b..e1511772e7 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java -@@ -202,6 +202,10 @@ public static boolean isARM() { +@@ -205,6 +205,10 @@ public class Platform { return isArch("arm.*"); } @@ -61586,20861 +58549,3 @@ index f4ee0546c70..635cdd18054 100644 public static boolean isPPC() { return isArch("ppc.*"); } - -From c51e546566c937354842a27696bd2221087101ae Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 28 Mar 2023 16:30:04 +0800 -Subject: [PATCH 002/140] Drop zgc part - ---- - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 6 +- - .../riscv/gc/z/zBarrierSetAssembler_riscv.cpp | 441 ------------------ - .../riscv/gc/z/zBarrierSetAssembler_riscv.hpp | 101 ---- - src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp | 212 --------- - src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp | 36 -- - src/hotspot/cpu/riscv/gc/z/z_riscv64.ad | 233 --------- - .../cpu/riscv/macroAssembler_riscv.cpp | 46 -- - .../cpu/riscv/macroAssembler_riscv.hpp | 9 - - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 10 - - 9 files changed, 1 insertion(+), 1093 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp - delete mode 100644 src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp - delete mode 100644 src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp - delete mode 100644 src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp - delete mode 100644 src/hotspot/cpu/riscv/gc/z/z_riscv64.ad - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 742c2126e60..bba3bd4709c 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -871,11 +871,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch - if (UseCompressedOops && !wide) { - __ decode_heap_oop(dest->as_register()); - } -- -- if (!UseZGC) { -- // Load barrier has not yet been applied, so ZGC can't verify the oop here -- __ verify_oop(dest->as_register()); -- } -+ __ verify_oop(dest->as_register()); - } - } - -diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp -deleted file mode 100644 -index 3d3f4d4d774..00000000000 ---- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.cpp -+++ /dev/null -@@ -1,441 +0,0 @@ --/* -- * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#include "precompiled.hpp" --#include "asm/macroAssembler.inline.hpp" --#include "code/codeBlob.hpp" --#include "code/vmreg.inline.hpp" --#include "gc/z/zBarrier.inline.hpp" --#include "gc/z/zBarrierSet.hpp" --#include "gc/z/zBarrierSetAssembler.hpp" --#include "gc/z/zBarrierSetRuntime.hpp" --#include "gc/z/zThreadLocalData.hpp" --#include "memory/resourceArea.hpp" --#include "runtime/sharedRuntime.hpp" --#include "utilities/macros.hpp" --#ifdef COMPILER1 --#include "c1/c1_LIRAssembler.hpp" --#include "c1/c1_MacroAssembler.hpp" --#include "gc/z/c1/zBarrierSetC1.hpp" --#endif // COMPILER1 --#ifdef COMPILER2 --#include "gc/z/c2/zBarrierSetC2.hpp" --#endif // COMPILER2 -- --#ifdef PRODUCT --#define BLOCK_COMMENT(str) /* nothing */ --#else --#define BLOCK_COMMENT(str) __ block_comment(str) --#endif -- --#undef __ --#define __ masm-> -- --void ZBarrierSetAssembler::load_at(MacroAssembler* masm, -- DecoratorSet decorators, -- BasicType type, -- Register dst, -- Address src, -- Register tmp1, -- Register tmp_thread) { -- if (!ZBarrierSet::barrier_needed(decorators, type)) { -- // Barrier not needed -- BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); -- return; -- } -- -- assert_different_registers(t1, src.base()); -- assert_different_registers(t0, t1, dst); -- -- Label done; -- -- // Load bad mask into temp register. -- __ la(t0, src); -- __ ld(t1, address_bad_mask_from_thread(xthread)); -- __ ld(dst, Address(t0)); -- -- // Test reference against bad mask. If mask bad, then we need to fix it up. -- __ andr(t1, dst, t1); -- __ beqz(t1, done); -- -- __ enter(); -- -- __ push_call_clobbered_registers_except(RegSet::of(dst)); -- -- if (c_rarg0 != dst) { -- __ mv(c_rarg0, dst); -- } -- -- __ mv(c_rarg1, t0); -- -- __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); -- -- // Make sure dst has the return value. -- if (dst != x10) { -- __ mv(dst, x10); -- } -- -- __ pop_call_clobbered_registers_except(RegSet::of(dst)); -- __ leave(); -- -- __ bind(done); --} -- --#ifdef ASSERT -- --void ZBarrierSetAssembler::store_at(MacroAssembler* masm, -- DecoratorSet decorators, -- BasicType type, -- Address dst, -- Register val, -- Register tmp1, -- Register tmp2) { -- // Verify value -- if (is_reference_type(type)) { -- // Note that src could be noreg, which means we -- // are storing null and can skip verification. -- if (val != noreg) { -- Label done; -- -- // tmp1 and tmp2 are often set to noreg. -- RegSet savedRegs = RegSet::of(t0); -- __ push_reg(savedRegs, sp); -- -- __ ld(t0, address_bad_mask_from_thread(xthread)); -- __ andr(t0, val, t0); -- __ beqz(t0, done); -- __ stop("Verify oop store failed"); -- __ should_not_reach_here(); -- __ bind(done); -- __ pop_reg(savedRegs, sp); -- } -- } -- -- // Store value -- BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2); --} -- --#endif // ASSERT -- --void ZBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, -- DecoratorSet decorators, -- bool is_oop, -- Register src, -- Register dst, -- Register count, -- RegSet saved_regs) { -- if (!is_oop) { -- // Barrier not needed -- return; -- } -- -- BLOCK_COMMENT("ZBarrierSetAssembler::arraycopy_prologue {"); -- -- assert_different_registers(src, count, t0); -- -- __ push_reg(saved_regs, sp); -- -- if (count == c_rarg0 && src == c_rarg1) { -- // exactly backwards!! -- __ xorr(c_rarg0, c_rarg0, c_rarg1); -- __ xorr(c_rarg1, c_rarg0, c_rarg1); -- __ xorr(c_rarg0, c_rarg0, c_rarg1); -- } else { -- __ mv(c_rarg0, src); -- __ mv(c_rarg1, count); -- } -- -- __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_array_addr(), 2); -- -- __ pop_reg(saved_regs, sp); -- -- BLOCK_COMMENT("} ZBarrierSetAssembler::arraycopy_prologue"); --} -- --void ZBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, -- Register jni_env, -- Register robj, -- Register tmp, -- Label& slowpath) { -- BLOCK_COMMENT("ZBarrierSetAssembler::try_resolve_jobject_in_native {"); -- -- assert_different_registers(jni_env, robj, tmp); -- -- // Resolve jobject -- BarrierSetAssembler::try_resolve_jobject_in_native(masm, jni_env, robj, tmp, slowpath); -- -- // Compute the offset of address bad mask from the field of jni_environment -- long int bad_mask_relative_offset = (long int) (in_bytes(ZThreadLocalData::address_bad_mask_offset()) - -- in_bytes(JavaThread::jni_environment_offset())); -- -- // Load the address bad mask -- __ ld(tmp, Address(jni_env, bad_mask_relative_offset)); -- -- // Check address bad mask -- __ andr(tmp, robj, tmp); -- __ bnez(tmp, slowpath); -- -- BLOCK_COMMENT("} ZBarrierSetAssembler::try_resolve_jobject_in_native"); --} -- --#ifdef COMPILER2 -- --OptoReg::Name ZBarrierSetAssembler::refine_register(const Node* node, OptoReg::Name opto_reg) { -- if (!OptoReg::is_reg(opto_reg)) { -- return OptoReg::Bad; -- } -- -- const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -- if (vm_reg->is_FloatRegister()) { -- return opto_reg & ~1; -- } -- -- return opto_reg; --} -- --#undef __ --#define __ _masm-> -- --class ZSaveLiveRegisters { --private: -- MacroAssembler* const _masm; -- RegSet _gp_regs; -- FloatRegSet _fp_regs; -- VectorRegSet _vp_regs; -- --public: -- void initialize(ZLoadBarrierStubC2* stub) { -- // Record registers that needs to be saved/restored -- RegMaskIterator rmi(stub->live()); -- while (rmi.has_next()) { -- const OptoReg::Name opto_reg = rmi.next(); -- if (OptoReg::is_reg(opto_reg)) { -- const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); -- if (vm_reg->is_Register()) { -- _gp_regs += RegSet::of(vm_reg->as_Register()); -- } else if (vm_reg->is_FloatRegister()) { -- _fp_regs += FloatRegSet::of(vm_reg->as_FloatRegister()); -- } else if (vm_reg->is_VectorRegister()) { -- const VMReg vm_reg_base = OptoReg::as_VMReg(opto_reg & ~(VectorRegisterImpl::max_slots_per_register - 1)); -- _vp_regs += VectorRegSet::of(vm_reg_base->as_VectorRegister()); -- } else { -- fatal("Unknown register type"); -- } -- } -- } -- -- // Remove C-ABI SOE registers, tmp regs and _ref register that will be updated -- _gp_regs -= RegSet::range(x18, x27) + RegSet::of(x2) + RegSet::of(x8, x9) + RegSet::of(x5, stub->ref()); -- } -- -- ZSaveLiveRegisters(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : -- _masm(masm), -- _gp_regs(), -- _fp_regs(), -- _vp_regs() { -- // Figure out what registers to save/restore -- initialize(stub); -- -- // Save registers -- __ push_reg(_gp_regs, sp); -- __ push_fp(_fp_regs, sp); -- __ push_vp(_vp_regs, sp); -- } -- -- ~ZSaveLiveRegisters() { -- // Restore registers -- __ pop_vp(_vp_regs, sp); -- __ pop_fp(_fp_regs, sp); -- __ pop_reg(_gp_regs, sp); -- } --}; -- --class ZSetupArguments { --private: -- MacroAssembler* const _masm; -- const Register _ref; -- const Address _ref_addr; -- --public: -- ZSetupArguments(MacroAssembler* masm, ZLoadBarrierStubC2* stub) : -- _masm(masm), -- _ref(stub->ref()), -- _ref_addr(stub->ref_addr()) { -- -- // Setup arguments -- if (_ref_addr.base() == noreg) { -- // No self healing -- if (_ref != c_rarg0) { -- __ mv(c_rarg0, _ref); -- } -- __ mv(c_rarg1, zr); -- } else { -- // Self healing -- if (_ref == c_rarg0) { -- // _ref is already at correct place -- __ la(c_rarg1, _ref_addr); -- } else if (_ref != c_rarg1) { -- // _ref is in wrong place, but not in c_rarg1, so fix it first -- __ la(c_rarg1, _ref_addr); -- __ mv(c_rarg0, _ref); -- } else if (_ref_addr.base() != c_rarg0) { -- assert(_ref == c_rarg1, "Mov ref first, vacating c_rarg0"); -- __ mv(c_rarg0, _ref); -- __ la(c_rarg1, _ref_addr); -- } else { -- assert(_ref == c_rarg1, "Need to vacate c_rarg1 and _ref_addr is using c_rarg0"); -- if (_ref_addr.base() == c_rarg0) { -- __ mv(t1, c_rarg1); -- __ la(c_rarg1, _ref_addr); -- __ mv(c_rarg0, t1); -- } else { -- ShouldNotReachHere(); -- } -- } -- } -- } -- -- ~ZSetupArguments() { -- // Transfer result -- if (_ref != x10) { -- __ mv(_ref, x10); -- } -- } --}; -- --#undef __ --#define __ masm-> -- --void ZBarrierSetAssembler::generate_c2_load_barrier_stub(MacroAssembler* masm, ZLoadBarrierStubC2* stub) const { -- BLOCK_COMMENT("ZLoadBarrierStubC2"); -- -- // Stub entry -- __ bind(*stub->entry()); -- -- { -- ZSaveLiveRegisters save_live_registers(masm, stub); -- ZSetupArguments setup_arguments(masm, stub); -- int32_t offset = 0; -- __ la_patchable(t0, stub->slow_path(), offset); -- __ jalr(x1, t0, offset); -- } -- -- // Stub exit -- __ j(*stub->continuation()); --} -- --#undef __ -- --#endif // COMPILER2 -- --#ifdef COMPILER1 --#undef __ --#define __ ce->masm()-> -- --void ZBarrierSetAssembler::generate_c1_load_barrier_test(LIR_Assembler* ce, -- LIR_Opr ref) const { -- assert_different_registers(xthread, ref->as_register(), t1); -- __ ld(t1, address_bad_mask_from_thread(xthread)); -- __ andr(t1, t1, ref->as_register()); --} -- --void ZBarrierSetAssembler::generate_c1_load_barrier_stub(LIR_Assembler* ce, -- ZLoadBarrierStubC1* stub) const { -- // Stub entry -- __ bind(*stub->entry()); -- -- Register ref = stub->ref()->as_register(); -- Register ref_addr = noreg; -- Register tmp = noreg; -- -- if (stub->tmp()->is_valid()) { -- // Load address into tmp register -- ce->leal(stub->ref_addr(), stub->tmp()); -- ref_addr = tmp = stub->tmp()->as_pointer_register(); -- } else { -- // Address already in register -- ref_addr = stub->ref_addr()->as_address_ptr()->base()->as_pointer_register(); -- } -- -- assert_different_registers(ref, ref_addr, noreg); -- -- // Save x10 unless it is the result or tmp register -- // Set up SP to accomodate parameters and maybe x10. -- if (ref != x10 && tmp != x10) { -- __ sub(sp, sp, 32); -- __ sd(x10, Address(sp, 16)); -- } else { -- __ sub(sp, sp, 16); -- } -- -- // Setup arguments and call runtime stub -- ce->store_parameter(ref_addr, 1); -- ce->store_parameter(ref, 0); -- -- __ far_call(stub->runtime_stub()); -- -- // Verify result -- __ verify_oop(x10, "Bad oop"); -- -- -- // Move result into place -- if (ref != x10) { -- __ mv(ref, x10); -- } -- -- // Restore x10 unless it is the result or tmp register -- if (ref != x10 && tmp != x10) { -- __ ld(x10, Address(sp, 16)); -- __ add(sp, sp, 32); -- } else { -- __ add(sp, sp, 16); -- } -- -- // Stub exit -- __ j(*stub->continuation()); --} -- --#undef __ --#define __ sasm-> -- --void ZBarrierSetAssembler::generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, -- DecoratorSet decorators) const { -- __ prologue("zgc_load_barrier stub", false); -- -- __ push_call_clobbered_registers_except(RegSet::of(x10)); -- -- // Setup arguments -- __ load_parameter(0, c_rarg0); -- __ load_parameter(1, c_rarg1); -- -- __ call_VM_leaf(ZBarrierSetRuntime::load_barrier_on_oop_field_preloaded_addr(decorators), 2); -- -- __ pop_call_clobbered_registers_except(RegSet::of(x10)); -- -- __ epilogue(); --} -- --#undef __ --#endif // COMPILER1 -diff --git a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp -deleted file mode 100644 -index dc07ab635fe..00000000000 ---- a/src/hotspot/cpu/riscv/gc/z/zBarrierSetAssembler_riscv.hpp -+++ /dev/null -@@ -1,101 +0,0 @@ --/* -- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP --#define CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP -- --#include "code/vmreg.hpp" --#include "oops/accessDecorators.hpp" --#ifdef COMPILER2 --#include "opto/optoreg.hpp" --#endif // COMPILER2 -- --#ifdef COMPILER1 --class LIR_Assembler; --class LIR_Opr; --class StubAssembler; --class ZLoadBarrierStubC1; --#endif // COMPILER1 -- --#ifdef COMPILER2 --class Node; --class ZLoadBarrierStubC2; --#endif // COMPILER2 -- --class ZBarrierSetAssembler : public ZBarrierSetAssemblerBase { --public: -- virtual void load_at(MacroAssembler* masm, -- DecoratorSet decorators, -- BasicType type, -- Register dst, -- Address src, -- Register tmp1, -- Register tmp_thread); -- --#ifdef ASSERT -- virtual void store_at(MacroAssembler* masm, -- DecoratorSet decorators, -- BasicType type, -- Address dst, -- Register val, -- Register tmp1, -- Register tmp2); --#endif // ASSERT -- -- virtual void arraycopy_prologue(MacroAssembler* masm, -- DecoratorSet decorators, -- bool is_oop, -- Register src, -- Register dst, -- Register count, -- RegSet saved_regs); -- -- virtual void try_resolve_jobject_in_native(MacroAssembler* masm, -- Register jni_env, -- Register robj, -- Register tmp, -- Label& slowpath); -- --#ifdef COMPILER1 -- void generate_c1_load_barrier_test(LIR_Assembler* ce, -- LIR_Opr ref) const; -- -- void generate_c1_load_barrier_stub(LIR_Assembler* ce, -- ZLoadBarrierStubC1* stub) const; -- -- void generate_c1_load_barrier_runtime_stub(StubAssembler* sasm, -- DecoratorSet decorators) const; --#endif // COMPILER1 -- --#ifdef COMPILER2 -- OptoReg::Name refine_register(const Node* node, -- OptoReg::Name opto_reg); -- -- void generate_c2_load_barrier_stub(MacroAssembler* masm, -- ZLoadBarrierStubC2* stub) const; --#endif // COMPILER2 --}; -- --#endif // CPU_RISCV_GC_Z_ZBARRIERSETASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp -deleted file mode 100644 -index d14997790af..00000000000 ---- a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.cpp -+++ /dev/null -@@ -1,212 +0,0 @@ --/* -- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "gc/shared/gcLogPrecious.hpp" --#include "gc/shared/gc_globals.hpp" --#include "gc/z/zGlobals.hpp" --#include "runtime/globals.hpp" --#include "runtime/os.hpp" --#include "utilities/globalDefinitions.hpp" --#include "utilities/powerOfTwo.hpp" -- --#ifdef LINUX --#include --#endif // LINUX -- --// --// The heap can have three different layouts, depending on the max heap size. --// --// Address Space & Pointer Layout 1 --// -------------------------------- --// --// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) --// . . --// . . --// . . --// +--------------------------------+ 0x0000014000000000 (20TB) --// | Remapped View | --// +--------------------------------+ 0x0000010000000000 (16TB) --// . . --// +--------------------------------+ 0x00000c0000000000 (12TB) --// | Marked1 View | --// +--------------------------------+ 0x0000080000000000 (8TB) --// | Marked0 View | --// +--------------------------------+ 0x0000040000000000 (4TB) --// . . --// +--------------------------------+ 0x0000000000000000 --// --// 6 4 4 4 4 --// 3 6 5 2 1 0 --// +--------------------+----+-----------------------------------------------+ --// |00000000 00000000 00|1111|11 11111111 11111111 11111111 11111111 11111111| --// +--------------------+----+-----------------------------------------------+ --// | | | --// | | * 41-0 Object Offset (42-bits, 4TB address space) --// | | --// | * 45-42 Metadata Bits (4-bits) 0001 = Marked0 (Address view 4-8TB) --// | 0010 = Marked1 (Address view 8-12TB) --// | 0100 = Remapped (Address view 16-20TB) --// | 1000 = Finalizable (Address view N/A) --// | --// * 63-46 Fixed (18-bits, always zero) --// --// --// Address Space & Pointer Layout 2 --// -------------------------------- --// --// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) --// . . --// . . --// . . --// +--------------------------------+ 0x0000280000000000 (40TB) --// | Remapped View | --// +--------------------------------+ 0x0000200000000000 (32TB) --// . . --// +--------------------------------+ 0x0000180000000000 (24TB) --// | Marked1 View | --// +--------------------------------+ 0x0000100000000000 (16TB) --// | Marked0 View | --// +--------------------------------+ 0x0000080000000000 (8TB) --// . . --// +--------------------------------+ 0x0000000000000000 --// --// 6 4 4 4 4 --// 3 7 6 3 2 0 --// +------------------+-----+------------------------------------------------+ --// |00000000 00000000 0|1111|111 11111111 11111111 11111111 11111111 11111111| --// +-------------------+----+------------------------------------------------+ --// | | | --// | | * 42-0 Object Offset (43-bits, 8TB address space) --// | | --// | * 46-43 Metadata Bits (4-bits) 0001 = Marked0 (Address view 8-16TB) --// | 0010 = Marked1 (Address view 16-24TB) --// | 0100 = Remapped (Address view 32-40TB) --// | 1000 = Finalizable (Address view N/A) --// | --// * 63-47 Fixed (17-bits, always zero) --// --// --// Address Space & Pointer Layout 3 --// -------------------------------- --// --// +--------------------------------+ 0x00007FFFFFFFFFFF (127TB) --// . . --// . . --// . . --// +--------------------------------+ 0x0000500000000000 (80TB) --// | Remapped View | --// +--------------------------------+ 0x0000400000000000 (64TB) --// . . --// +--------------------------------+ 0x0000300000000000 (48TB) --// | Marked1 View | --// +--------------------------------+ 0x0000200000000000 (32TB) --// | Marked0 View | --// +--------------------------------+ 0x0000100000000000 (16TB) --// . . --// +--------------------------------+ 0x0000000000000000 --// --// 6 4 4 4 4 --// 3 8 7 4 3 0 --// +------------------+----+-------------------------------------------------+ --// |00000000 00000000 |1111|1111 11111111 11111111 11111111 11111111 11111111| --// +------------------+----+-------------------------------------------------+ --// | | | --// | | * 43-0 Object Offset (44-bits, 16TB address space) --// | | --// | * 47-44 Metadata Bits (4-bits) 0001 = Marked0 (Address view 16-32TB) --// | 0010 = Marked1 (Address view 32-48TB) --// | 0100 = Remapped (Address view 64-80TB) --// | 1000 = Finalizable (Address view N/A) --// | --// * 63-48 Fixed (16-bits, always zero) --// -- --// Default value if probing is not implemented for a certain platform: 128TB --static const size_t DEFAULT_MAX_ADDRESS_BIT = 47; --// Minimum value returned, if probing fails: 64GB --static const size_t MINIMUM_MAX_ADDRESS_BIT = 36; -- --static size_t probe_valid_max_address_bit() { --#ifdef LINUX -- size_t max_address_bit = 0; -- const size_t page_size = os::vm_page_size(); -- for (size_t i = DEFAULT_MAX_ADDRESS_BIT; i > MINIMUM_MAX_ADDRESS_BIT; --i) { -- const uintptr_t base_addr = ((uintptr_t) 1U) << i; -- if (msync((void*)base_addr, page_size, MS_ASYNC) == 0) { -- // msync suceeded, the address is valid, and maybe even already mapped. -- max_address_bit = i; -- break; -- } -- if (errno != ENOMEM) { -- // Some error occured. This should never happen, but msync -- // has some undefined behavior, hence ignore this bit. --#ifdef ASSERT -- fatal("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); --#else // ASSERT -- log_warning_p(gc)("Received '%s' while probing the address space for the highest valid bit", os::errno_name(errno)); --#endif // ASSERT -- continue; -- } -- // Since msync failed with ENOMEM, the page might not be mapped. -- // Try to map it, to see if the address is valid. -- void* const result_addr = mmap((void*) base_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); -- if (result_addr != MAP_FAILED) { -- munmap(result_addr, page_size); -- } -- if ((uintptr_t) result_addr == base_addr) { -- // address is valid -- max_address_bit = i; -- break; -- } -- } -- if (max_address_bit == 0) { -- // probing failed, allocate a very high page and take that bit as the maximum -- const uintptr_t high_addr = ((uintptr_t) 1U) << DEFAULT_MAX_ADDRESS_BIT; -- void* const result_addr = mmap((void*) high_addr, page_size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0); -- if (result_addr != MAP_FAILED) { -- max_address_bit = BitsPerSize_t - count_leading_zeros((size_t) result_addr) - 1; -- munmap(result_addr, page_size); -- } -- } -- log_info_p(gc, init)("Probing address space for the highest valid bit: " SIZE_FORMAT, max_address_bit); -- return MAX2(max_address_bit, MINIMUM_MAX_ADDRESS_BIT); --#else // LINUX -- return DEFAULT_MAX_ADDRESS_BIT; --#endif // LINUX --} -- --size_t ZPlatformAddressOffsetBits() { -- const static size_t valid_max_address_offset_bits = probe_valid_max_address_bit() + 1; -- const size_t max_address_offset_bits = valid_max_address_offset_bits - 3; -- const size_t min_address_offset_bits = max_address_offset_bits - 2; -- const size_t address_offset = round_up_power_of_2(MaxHeapSize * ZVirtualToPhysicalRatio); -- const size_t address_offset_bits = log2i_exact(address_offset); -- return clamp(address_offset_bits, min_address_offset_bits, max_address_offset_bits); --} -- --size_t ZPlatformAddressMetadataShift() { -- return ZPlatformAddressOffsetBits(); --} -diff --git a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp b/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp -deleted file mode 100644 -index f20ecd9b073..00000000000 ---- a/src/hotspot/cpu/riscv/gc/z/zGlobals_riscv.hpp -+++ /dev/null -@@ -1,36 +0,0 @@ --/* -- * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP --#define CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP -- --const size_t ZPlatformGranuleSizeShift = 21; // 2MB --const size_t ZPlatformHeapViews = 3; --const size_t ZPlatformCacheLineSize = 64; -- --size_t ZPlatformAddressOffsetBits(); --size_t ZPlatformAddressMetadataShift(); -- --#endif // CPU_RISCV_GC_Z_ZGLOBALS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad b/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad -deleted file mode 100644 -index 6b6f87814a5..00000000000 ---- a/src/hotspot/cpu/riscv/gc/z/z_riscv64.ad -+++ /dev/null -@@ -1,233 +0,0 @@ --// --// Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. --// Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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. --// -- --source_hpp %{ -- --#include "gc/shared/gc_globals.hpp" --#include "gc/z/c2/zBarrierSetC2.hpp" --#include "gc/z/zThreadLocalData.hpp" -- --%} -- --source %{ -- --static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, int barrier_data) { -- if (barrier_data == ZLoadBarrierElided) { -- return; -- } -- ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); -- __ ld(tmp, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -- __ andr(tmp, tmp, ref); -- __ bnez(tmp, *stub->entry(), true /* far */); -- __ bind(*stub->continuation()); --} -- --static void z_load_barrier_slow_path(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp) { -- ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, ZLoadBarrierStrong); -- __ j(*stub->entry()); -- __ bind(*stub->continuation()); --} -- --%} -- --// Load Pointer --instruct zLoadP(iRegPNoSp dst, memory mem) --%{ -- match(Set dst (LoadP mem)); -- predicate(UseZGC && (n->as_Load()->barrier_data() != 0)); -- effect(TEMP dst); -- -- ins_cost(4 * DEFAULT_COST); -- -- format %{ "ld $dst, $mem, #@zLoadP" %} -- -- ins_encode %{ -- const Address ref_addr (as_Register($mem$$base), $mem$$disp); -- __ ld($dst$$Register, ref_addr); -- z_load_barrier(_masm, this, ref_addr, $dst$$Register, t0 /* tmp */, barrier_data()); -- %} -- -- ins_pipe(iload_reg_mem); --%} -- --instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ -- match(Set res (CompareAndSwapP mem (Binary oldval newval))); -- match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); -- predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -- effect(KILL cr, TEMP_DEF res); -- -- ins_cost(2 * VOLATILE_REF_COST); -- -- format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapP\n\t" -- "mv $res, $res == $oldval" %} -- -- ins_encode %{ -- Label failed; -- guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, -- true /* result_as_bool */); -- __ beqz($res$$Register, failed); -- __ mv(t0, $oldval$$Register); -- __ bind(failed); -- if (barrier_data() != ZLoadBarrierElided) { -- Label good; -- __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); -- __ andr(t1, t1, t0); -- __ beqz(t1, good); -- z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register, -- true /* result_as_bool */); -- __ bind(good); -- } -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{ -- match(Set res (CompareAndSwapP mem (Binary oldval newval))); -- match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); -- predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong)); -- effect(KILL cr, TEMP_DEF res); -- -- ins_cost(2 * VOLATILE_REF_COST); -- -- format %{ "cmpxchg $mem, $oldval, $newval, #@zCompareAndSwapPAcq\n\t" -- "mv $res, $res == $oldval" %} -- -- ins_encode %{ -- Label failed; -- guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, -- true /* result_as_bool */); -- __ beqz($res$$Register, failed); -- __ mv(t0, $oldval$$Register); -- __ bind(failed); -- if (barrier_data() != ZLoadBarrierElided) { -- Label good; -- __ ld(t1, Address(xthread, ZThreadLocalData::address_bad_mask_offset()), t1 /* tmp */); -- __ andr(t1, t1, t0); -- __ beqz(t1, good); -- z_load_barrier_slow_path(_masm, this, Address($mem$$Register), t0 /* ref */, t1 /* tmp */); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register, -- true /* result_as_bool */); -- __ bind(good); -- } -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ -- match(Set res (CompareAndExchangeP mem (Binary oldval newval))); -- predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -- effect(TEMP_DEF res); -- -- ins_cost(2 * VOLATILE_REF_COST); -- -- format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangeP" %} -- -- ins_encode %{ -- guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); -- if (barrier_data() != ZLoadBarrierElided) { -- Label good; -- __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -- __ andr(t0, t0, $res$$Register); -- __ beqz(t0, good); -- z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::relaxed /* acquire */, Assembler::rl /* release */, $res$$Register); -- __ bind(good); -- } -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) %{ -- match(Set res (CompareAndExchangeP mem (Binary oldval newval))); -- predicate(UseZGC && needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); -- effect(TEMP_DEF res); -- -- ins_cost(2 * VOLATILE_REF_COST); -- -- format %{ "cmpxchg $res = $mem, $oldval, $newval, #@zCompareAndExchangePAcq" %} -- -- ins_encode %{ -- guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); -- if (barrier_data() != ZLoadBarrierElided) { -- Label good; -- __ ld(t0, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -- __ andr(t0, t0, $res$$Register); -- __ beqz(t0, good); -- z_load_barrier_slow_path(_masm, this, Address($mem$$Register), $res$$Register /* ref */, t0 /* tmp */); -- __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::int64, -- Assembler::aq /* acquire */, Assembler::rl /* release */, $res$$Register); -- __ bind(good); -- } -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct zGetAndSetP(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ -- match(Set prev (GetAndSetP mem newv)); -- predicate(UseZGC && !needs_acquiring_load_reserved(n) && n->as_LoadStore()->barrier_data() != 0); -- effect(TEMP_DEF prev, KILL cr); -- -- ins_cost(2 * VOLATILE_REF_COST); -- -- format %{ "atomic_xchg $prev, $newv, [$mem], #@zGetAndSetP" %} -- -- ins_encode %{ -- __ atomic_xchg($prev$$Register, $newv$$Register, as_Register($mem$$base)); -- z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); -- %} -- -- ins_pipe(pipe_serial); --%} -- --instruct zGetAndSetPAcq(indirect mem, iRegP newv, iRegPNoSp prev, rFlagsReg cr) %{ -- match(Set prev (GetAndSetP mem newv)); -- predicate(UseZGC && needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() != 0)); -- effect(TEMP_DEF prev, KILL cr); -- -- ins_cost(VOLATILE_REF_COST); -- -- format %{ "atomic_xchg_acq $prev, $newv, [$mem], #@zGetAndSetPAcq" %} -- -- ins_encode %{ -- __ atomic_xchgal($prev$$Register, $newv$$Register, as_Register($mem$$base)); -- z_load_barrier(_masm, this, Address(noreg, 0), $prev$$Register, t0 /* tmp */, barrier_data()); -- %} -- ins_pipe(pipe_serial); --%} -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 86710295444..9d2cc4cf89f 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1046,52 +1046,6 @@ int MacroAssembler::pop_fp(unsigned int bitset, Register stack) { - return count; - } - --#ifdef COMPILER2 --int MacroAssembler::push_vp(unsigned int bitset, Register stack) { -- CompressibleRegion cr(this); -- int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -- -- // Scan bitset to accumulate register pairs -- unsigned char regs[32]; -- int count = 0; -- for (int reg = 31; reg >= 0; reg--) { -- if ((1U << 31) & bitset) { -- regs[count++] = reg; -- } -- bitset <<= 1; -- } -- -- for (int i = 0; i < count; i++) { -- sub(stack, stack, vector_size_in_bytes); -- vs1r_v(as_VectorRegister(regs[i]), stack); -- } -- -- return count * vector_size_in_bytes / wordSize; --} -- --int MacroAssembler::pop_vp(unsigned int bitset, Register stack) { -- CompressibleRegion cr(this); -- int vector_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -- -- // Scan bitset to accumulate register pairs -- unsigned char regs[32]; -- int count = 0; -- for (int reg = 31; reg >= 0; reg--) { -- if ((1U << 31) & bitset) { -- regs[count++] = reg; -- } -- bitset <<= 1; -- } -- -- for (int i = count - 1; i >= 0; i--) { -- vl1r_v(as_VectorRegister(regs[i]), stack); -- add(stack, stack, vector_size_in_bytes); -- } -- -- return count * vector_size_in_bytes / wordSize; --} --#endif // COMPILER2 -- - void MacroAssembler::push_call_clobbered_registers_except(RegSet exclude) { - CompressibleRegion cr(this); - // Push integer registers x7, x10-x17, x28-x31. -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 23e09475be1..b2f0455a1f1 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -484,12 +484,6 @@ class MacroAssembler: public Assembler { - void pop_reg(Register Rd); - int push_reg(unsigned int bitset, Register stack); - int pop_reg(unsigned int bitset, Register stack); -- void push_fp(FloatRegSet regs, Register stack) { if (regs.bits()) push_fp(regs.bits(), stack); } -- void pop_fp(FloatRegSet regs, Register stack) { if (regs.bits()) pop_fp(regs.bits(), stack); } --#ifdef COMPILER2 -- void push_vp(VectorRegSet regs, Register stack) { if (regs.bits()) push_vp(regs.bits(), stack); } -- void pop_vp(VectorRegSet regs, Register stack) { if (regs.bits()) pop_vp(regs.bits(), stack); } --#endif // COMPILER2 - - // Push and pop everything that might be clobbered by a native - // runtime call except t0 and t1. (They are always -@@ -783,9 +777,6 @@ class MacroAssembler: public Assembler { - int push_fp(unsigned int bitset, Register stack); - int pop_fp(unsigned int bitset, Register stack); - -- int push_vp(unsigned int bitset, Register stack); -- int pop_vp(unsigned int bitset, Register stack); -- - // vext - void vmnot_m(VectorRegister vd, VectorRegister vs); - void vncvt_x_x_w(VectorRegister vd, VectorRegister vs, VectorMask vm = unmasked); -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index b3fdd04db1b..b05edf7172c 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -546,16 +546,6 @@ class StubGenerator: public StubCodeGenerator { - // make sure object is 'reasonable' - __ beqz(x10, exit); // if obj is NULL it is OK - --#if INCLUDE_ZGC -- if (UseZGC) { -- // Check if mask is good. -- // verifies that ZAddressBadMask & x10 == 0 -- __ ld(c_rarg3, Address(xthread, ZThreadLocalData::address_bad_mask_offset())); -- __ andr(c_rarg2, x10, c_rarg3); -- __ bnez(c_rarg2, error); -- } --#endif -- - // Check if the oop is in the right area of memory - __ mv(c_rarg3, (intptr_t) Universe::verify_oop_mask()); - __ andr(c_rarg2, x10, c_rarg3); - -From 7772140df96747b42b13007d0827fc21d2a8b926 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Mon, 27 Mar 2023 15:43:39 +0800 -Subject: [PATCH 003/140] Drop the C2 Vector part - ---- - make/hotspot/gensrc/GensrcAdlc.gmk | 1 - - .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 325 --- - .../cpu/riscv/c2_MacroAssembler_riscv.hpp | 52 - - src/hotspot/cpu/riscv/globals_riscv.hpp | 8 +- - .../cpu/riscv/macroAssembler_riscv.cpp | 22 +- - .../cpu/riscv/macroAssembler_riscv.hpp | 4 +- - src/hotspot/cpu/riscv/matcher_riscv.hpp | 44 +- - src/hotspot/cpu/riscv/register_riscv.cpp | 5 - - src/hotspot/cpu/riscv/register_riscv.hpp | 4 +- - src/hotspot/cpu/riscv/riscv.ad | 476 +--- - src/hotspot/cpu/riscv/riscv_v.ad | 2065 ----------------- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 61 +- - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 110 - - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 4 - - src/hotspot/cpu/riscv/vmreg_riscv.cpp | 10 +- - src/hotspot/cpu/riscv/vmreg_riscv.hpp | 17 +- - 16 files changed, 41 insertions(+), 3167 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/riscv_v.ad - -diff --git a/make/hotspot/gensrc/GensrcAdlc.gmk b/make/hotspot/gensrc/GensrcAdlc.gmk -index 67f4c6f0574..51137b99db2 100644 ---- a/make/hotspot/gensrc/GensrcAdlc.gmk -+++ b/make/hotspot/gensrc/GensrcAdlc.gmk -@@ -152,7 +152,6 @@ ifeq ($(call check-jvm-feature, compiler2), true) - - ifeq ($(HOTSPOT_TARGET_CPU_ARCH), riscv) - AD_SRC_FILES += $(call uniq, $(wildcard $(foreach d, $(AD_SRC_ROOTS), \ -- $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_v.ad \ - $d/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/$(HOTSPOT_TARGET_CPU_ARCH)_b.ad \ - ))) - endif -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -index 27770dc17aa..73f84a724ca 100644 ---- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -@@ -1319,328 +1319,3 @@ void C2_MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRe - - bind(Done); - } -- --void C2_MacroAssembler::element_compare(Register a1, Register a2, Register result, Register cnt, Register tmp1, Register tmp2, -- VectorRegister vr1, VectorRegister vr2, VectorRegister vrs, bool islatin, Label &DONE) { -- Label loop; -- Assembler::SEW sew = islatin ? Assembler::e8 : Assembler::e16; -- -- bind(loop); -- vsetvli(tmp1, cnt, sew, Assembler::m2); -- vlex_v(vr1, a1, sew); -- vlex_v(vr2, a2, sew); -- vmsne_vv(vrs, vr1, vr2); -- vfirst_m(tmp2, vrs); -- bgez(tmp2, DONE); -- sub(cnt, cnt, tmp1); -- if (!islatin) { -- slli(tmp1, tmp1, 1); // get byte counts -- } -- add(a1, a1, tmp1); -- add(a2, a2, tmp1); -- bnez(cnt, loop); -- -- mv(result, true); --} -- --void C2_MacroAssembler::string_equals_v(Register a1, Register a2, Register result, Register cnt, int elem_size) { -- Label DONE; -- Register tmp1 = t0; -- Register tmp2 = t1; -- -- BLOCK_COMMENT("string_equals_v {"); -- -- mv(result, false); -- -- if (elem_size == 2) { -- srli(cnt, cnt, 1); -- } -- -- element_compare(a1, a2, result, cnt, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); -- -- bind(DONE); -- BLOCK_COMMENT("} string_equals_v"); --} -- --// used by C2 ClearArray patterns. --// base: Address of a buffer to be zeroed --// cnt: Count in HeapWords --// --// base, cnt, v0, v1 and t0 are clobbered. --void C2_MacroAssembler::clear_array_v(Register base, Register cnt) { -- Label loop; -- -- // making zero words -- vsetvli(t0, cnt, Assembler::e64, Assembler::m4); -- vxor_vv(v0, v0, v0); -- -- bind(loop); -- vsetvli(t0, cnt, Assembler::e64, Assembler::m4); -- vse64_v(v0, base); -- sub(cnt, cnt, t0); -- shadd(base, t0, base, t0, 3); -- bnez(cnt, loop); --} -- --void C2_MacroAssembler::arrays_equals_v(Register a1, Register a2, Register result, -- Register cnt1, int elem_size) { -- Label DONE; -- Register tmp1 = t0; -- Register tmp2 = t1; -- Register cnt2 = tmp2; -- int length_offset = arrayOopDesc::length_offset_in_bytes(); -- int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); -- -- BLOCK_COMMENT("arrays_equals_v {"); -- -- // if (a1 == a2), return true -- mv(result, true); -- beq(a1, a2, DONE); -- -- mv(result, false); -- // if a1 == null or a2 == null, return false -- beqz(a1, DONE); -- beqz(a2, DONE); -- // if (a1.length != a2.length), return false -- lwu(cnt1, Address(a1, length_offset)); -- lwu(cnt2, Address(a2, length_offset)); -- bne(cnt1, cnt2, DONE); -- -- la(a1, Address(a1, base_offset)); -- la(a2, Address(a2, base_offset)); -- -- element_compare(a1, a2, result, cnt1, tmp1, tmp2, v0, v2, v0, elem_size == 1, DONE); -- -- bind(DONE); -- -- BLOCK_COMMENT("} arrays_equals_v"); --} -- --void C2_MacroAssembler::string_compare_v(Register str1, Register str2, Register cnt1, Register cnt2, -- Register result, Register tmp1, Register tmp2, int encForm) { -- Label DIFFERENCE, DONE, L, loop; -- bool encLL = encForm == StrIntrinsicNode::LL; -- bool encLU = encForm == StrIntrinsicNode::LU; -- bool encUL = encForm == StrIntrinsicNode::UL; -- -- bool str1_isL = encLL || encLU; -- bool str2_isL = encLL || encUL; -- -- int minCharsInWord = encLL ? wordSize : wordSize / 2; -- -- BLOCK_COMMENT("string_compare {"); -- -- // for Lating strings, 1 byte for 1 character -- // for UTF16 strings, 2 bytes for 1 character -- if (!str1_isL) -- sraiw(cnt1, cnt1, 1); -- if (!str2_isL) -- sraiw(cnt2, cnt2, 1); -- -- // if str1 == str2, return the difference -- // save the minimum of the string lengths in cnt2. -- sub(result, cnt1, cnt2); -- bgt(cnt1, cnt2, L); -- mv(cnt2, cnt1); -- bind(L); -- -- if (str1_isL == str2_isL) { // LL or UU -- element_compare(str1, str2, zr, cnt2, tmp1, tmp2, v2, v4, v1, encLL, DIFFERENCE); -- j(DONE); -- } else { // LU or UL -- Register strL = encLU ? str1 : str2; -- Register strU = encLU ? str2 : str1; -- VectorRegister vstr1 = encLU ? v4 : v0; -- VectorRegister vstr2 = encLU ? v0 : v4; -- -- bind(loop); -- vsetvli(tmp1, cnt2, Assembler::e8, Assembler::m2); -- vle8_v(vstr1, strL); -- vsetvli(tmp1, cnt2, Assembler::e16, Assembler::m4); -- vzext_vf2(vstr2, vstr1); -- vle16_v(vstr1, strU); -- vmsne_vv(v0, vstr2, vstr1); -- vfirst_m(tmp2, v0); -- bgez(tmp2, DIFFERENCE); -- sub(cnt2, cnt2, tmp1); -- add(strL, strL, tmp1); -- shadd(strU, tmp1, strU, tmp1, 1); -- bnez(cnt2, loop); -- j(DONE); -- } -- bind(DIFFERENCE); -- slli(tmp1, tmp2, 1); -- add(str1, str1, str1_isL ? tmp2 : tmp1); -- add(str2, str2, str2_isL ? tmp2 : tmp1); -- str1_isL ? lbu(tmp1, Address(str1, 0)) : lhu(tmp1, Address(str1, 0)); -- str2_isL ? lbu(tmp2, Address(str2, 0)) : lhu(tmp2, Address(str2, 0)); -- sub(result, tmp1, tmp2); -- -- bind(DONE); --} -- --void C2_MacroAssembler::byte_array_inflate_v(Register src, Register dst, Register len, Register tmp) { -- Label loop; -- assert_different_registers(src, dst, len, tmp, t0); -- -- BLOCK_COMMENT("byte_array_inflate_v {"); -- bind(loop); -- vsetvli(tmp, len, Assembler::e8, Assembler::m2); -- vle8_v(v2, src); -- vsetvli(t0, len, Assembler::e16, Assembler::m4); -- vzext_vf2(v0, v2); -- vse16_v(v0, dst); -- sub(len, len, tmp); -- add(src, src, tmp); -- shadd(dst, tmp, dst, tmp, 1); -- bnez(len, loop); -- BLOCK_COMMENT("} byte_array_inflate_v"); --} -- --// Compress char[] array to byte[]. --// result: the array length if every element in array can be encoded; 0, otherwise. --void C2_MacroAssembler::char_array_compress_v(Register src, Register dst, Register len, Register result, Register tmp) { -- Label done; -- encode_iso_array_v(src, dst, len, result, tmp); -- beqz(len, done); -- mv(result, zr); -- bind(done); --} -- --// result: the number of elements had been encoded. --void C2_MacroAssembler::encode_iso_array_v(Register src, Register dst, Register len, Register result, Register tmp) { -- Label loop, DIFFERENCE, DONE; -- -- BLOCK_COMMENT("encode_iso_array_v {"); -- mv(result, 0); -- -- bind(loop); -- mv(tmp, 0xff); -- vsetvli(t0, len, Assembler::e16, Assembler::m2); -- vle16_v(v2, src); -- // if element > 0xff, stop -- vmsgtu_vx(v1, v2, tmp); -- vfirst_m(tmp, v1); -- vmsbf_m(v0, v1); -- // compress char to byte -- vsetvli(t0, len, Assembler::e8); -- vncvt_x_x_w(v1, v2, Assembler::v0_t); -- vse8_v(v1, dst, Assembler::v0_t); -- -- bgez(tmp, DIFFERENCE); -- add(result, result, t0); -- add(dst, dst, t0); -- sub(len, len, t0); -- shadd(src, t0, src, t0, 1); -- bnez(len, loop); -- j(DONE); -- -- bind(DIFFERENCE); -- add(result, result, tmp); -- -- bind(DONE); -- BLOCK_COMMENT("} encode_iso_array_v"); --} -- --void C2_MacroAssembler::count_positives_v(Register ary, Register len, Register result, Register tmp) { -- Label LOOP, SET_RESULT, DONE; -- -- BLOCK_COMMENT("count_positives_v {"); -- mv(result, zr); -- -- bind(LOOP); -- vsetvli(t0, len, Assembler::e8, Assembler::m4); -- vle8_v(v0, ary); -- vmslt_vx(v0, v0, zr); -- vfirst_m(tmp, v0); -- bgez(tmp, SET_RESULT); -- // if tmp == -1, all bytes are positive -- add(result, result, t0); -- -- sub(len, len, t0); -- add(ary, ary, t0); -- bnez(len, LOOP); -- j(DONE); -- -- // add remaining positive bytes count -- bind(SET_RESULT); -- add(result, result, tmp); -- -- bind(DONE); -- BLOCK_COMMENT("} count_positives_v"); --} -- --void C2_MacroAssembler::string_indexof_char_v(Register str1, Register cnt1, -- Register ch, Register result, -- Register tmp1, Register tmp2, -- bool isL) { -- mv(result, zr); -- -- Label loop, MATCH, DONE; -- Assembler::SEW sew = isL ? Assembler::e8 : Assembler::e16; -- bind(loop); -- vsetvli(tmp1, cnt1, sew, Assembler::m4); -- vlex_v(v0, str1, sew); -- vmseq_vx(v0, v0, ch); -- vfirst_m(tmp2, v0); -- bgez(tmp2, MATCH); // if equal, return index -- -- add(result, result, tmp1); -- sub(cnt1, cnt1, tmp1); -- if (!isL) slli(tmp1, tmp1, 1); -- add(str1, str1, tmp1); -- bnez(cnt1, loop); -- -- mv(result, -1); -- j(DONE); -- -- bind(MATCH); -- add(result, result, tmp2); -- -- bind(DONE); --} -- --// Set dst to NaN if any NaN input. --void C2_MacroAssembler::minmax_FD_v(VectorRegister dst, VectorRegister src1, VectorRegister src2, -- bool is_double, bool is_min) { -- assert_different_registers(dst, src1, src2); -- -- vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); -- -- is_min ? vfmin_vv(dst, src1, src2) -- : vfmax_vv(dst, src1, src2); -- -- vmfne_vv(v0, src1, src1); -- vfadd_vv(dst, src1, src1, Assembler::v0_t); -- vmfne_vv(v0, src2, src2); -- vfadd_vv(dst, src2, src2, Assembler::v0_t); --} -- --// Set dst to NaN if any NaN input. --void C2_MacroAssembler::reduce_minmax_FD_v(FloatRegister dst, -- FloatRegister src1, VectorRegister src2, -- VectorRegister tmp1, VectorRegister tmp2, -- bool is_double, bool is_min) { -- assert_different_registers(src2, tmp1, tmp2); -- -- Label L_done, L_NaN; -- vsetvli(t0, x0, is_double ? Assembler::e64 : Assembler::e32); -- vfmv_s_f(tmp2, src1); -- -- is_min ? vfredmin_vs(tmp1, src2, tmp2) -- : vfredmax_vs(tmp1, src2, tmp2); -- -- fsflags(zr); -- // Checking NaNs -- vmflt_vf(tmp2, src2, src1); -- frflags(t0); -- bnez(t0, L_NaN); -- j(L_done); -- -- bind(L_NaN); -- vfmv_s_f(tmp2, src1); -- vfredsum_vs(tmp1, src2, tmp2); -- -- bind(L_done); -- vfmv_f_s(dst, tmp1); --} -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -index c71df4c101b..90b6554af02 100644 ---- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -@@ -28,13 +28,6 @@ - - // C2_MacroAssembler contains high-level macros for C2 - -- private: -- void element_compare(Register r1, Register r2, -- Register result, Register cnt, -- Register tmp1, Register tmp2, -- VectorRegister vr1, VectorRegister vr2, -- VectorRegister vrs, -- bool is_latin, Label& DONE); - public: - - void string_compare(Register str1, Register str2, -@@ -145,49 +138,4 @@ - FloatRegister src1, FloatRegister src2, - bool is_double, bool is_min); - -- // intrinsic methods implemented by rvv instructions -- void string_equals_v(Register r1, Register r2, -- Register result, Register cnt1, -- int elem_size); -- -- void arrays_equals_v(Register r1, Register r2, -- Register result, Register cnt1, -- int elem_size); -- -- void string_compare_v(Register str1, Register str2, -- Register cnt1, Register cnt2, -- Register result, -- Register tmp1, Register tmp2, -- int encForm); -- -- void clear_array_v(Register base, Register cnt); -- -- void byte_array_inflate_v(Register src, Register dst, -- Register len, Register tmp); -- -- void char_array_compress_v(Register src, Register dst, -- Register len, Register result, -- Register tmp); -- -- void encode_iso_array_v(Register src, Register dst, -- Register len, Register result, -- Register tmp); -- -- void count_positives_v(Register ary, Register len, -- Register result, Register tmp); -- -- void string_indexof_char_v(Register str1, Register cnt1, -- Register ch, Register result, -- Register tmp1, Register tmp2, -- bool isL); -- -- void minmax_FD_v(VectorRegister dst, -- VectorRegister src1, VectorRegister src2, -- bool is_double, bool is_min); -- -- void reduce_minmax_FD_v(FloatRegister dst, -- FloatRegister src1, VectorRegister src2, -- VectorRegister tmp1, VectorRegister tmp2, -- bool is_double, bool is_min); -- - #endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index cbfc0583883..845064d6cbc 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -90,10 +90,8 @@ define_pd_global(intx, InlineSmallCode, 1000); - "Extend fence.i to fence.i + fence.") \ - product(bool, AvoidUnalignedAccesses, true, \ - "Avoid generating unaligned memory accesses") \ -- product(bool, UseRVV, false, EXPERIMENTAL, "Use RVV instructions") \ -- product(bool, UseRVB, false, EXPERIMENTAL, "Use RVB instructions") \ -- product(bool, UseRVC, false, EXPERIMENTAL, "Use RVC instructions") \ -- product(bool, UseRVVForBigIntegerShiftIntrinsics, true, \ -- "Use RVV instructions for left/right shift of BigInteger") -+ experimental(bool, UseRVV, false, "Use RVV instructions") \ -+ experimental(bool, UseRVB, false, "Use RVB instructions") \ -+ experimental(bool, UseRVC, false, "Use RVC instructions") - - #endif // CPU_RISCV_GLOBALS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 9d2cc4cf89f..8b8d126f6c9 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1086,7 +1086,7 @@ void MacroAssembler::popa() { - pop_reg(0xffffffe2, sp); - } - --void MacroAssembler::push_CPU_state(bool save_vectors, int vector_size_in_bytes) { -+void MacroAssembler::push_CPU_state() { - CompressibleRegion cr(this); - // integer registers, except zr(x0) & ra(x1) & sp(x2) & gp(x3) & tp(x4) - push_reg(0xffffffe0, sp); -@@ -1096,28 +1096,10 @@ void MacroAssembler::push_CPU_state(bool save_vectors, int vector_size_in_bytes) - for (int i = 0; i < 32; i++) { - fsd(as_FloatRegister(i), Address(sp, i * wordSize)); - } -- -- // vector registers -- if (save_vectors) { -- sub(sp, sp, vector_size_in_bytes * VectorRegisterImpl::number_of_registers); -- vsetvli(t0, x0, Assembler::e64, Assembler::m8); -- for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { -- add(t0, sp, vector_size_in_bytes * i); -- vse64_v(as_VectorRegister(i), t0); -- } -- } - } - --void MacroAssembler::pop_CPU_state(bool restore_vectors, int vector_size_in_bytes) { -+void MacroAssembler::pop_CPU_state() { - CompressibleRegion cr(this); -- // vector registers -- if (restore_vectors) { -- vsetvli(t0, x0, Assembler::e64, Assembler::m8); -- for (int i = 0; i < VectorRegisterImpl::number_of_registers; i += 8) { -- vle64_v(as_VectorRegister(i), sp); -- add(sp, sp, vector_size_in_bytes * 8); -- } -- } - - // float registers - for (int i = 0; i < 32; i++) { -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index b2f0455a1f1..b43131514c1 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -501,8 +501,8 @@ class MacroAssembler: public Assembler { - - void pusha(); - void popa(); -- void push_CPU_state(bool save_vectors = false, int vector_size_in_bytes = 0); -- void pop_CPU_state(bool restore_vectors = false, int vector_size_in_bytes = 0); -+ void push_CPU_state(); -+ void pop_CPU_state(); - - // if heap base register is used - reinit it with the correct value - void reinit_heapbase(); -diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp -index 23a75d20502..4c7fabd7240 100644 ---- a/src/hotspot/cpu/riscv/matcher_riscv.hpp -+++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp -@@ -31,16 +31,9 @@ - // false => size gets scaled to BytesPerLong, ok. - static const bool init_array_count_is_in_bytes = false; - -- // Whether this platform implements the scalable vector feature -- static const bool implements_scalable_vector = true; -- -- static const bool supports_scalable_vector() { -- return UseRVV; -- } -- -- // riscv supports misaligned vectors store/load. -+ // riscv doesn't support misaligned vectors store/load on JDK11. - static constexpr bool misaligned_vectors_ok() { -- return true; -+ return false; - } - - // Whether code generation need accurate ConvI2L types. -@@ -53,9 +46,6 @@ - // the cpu only look at the lower 5/6 bits anyway? - static const bool need_masked_shift_count = false; - -- // No support for generic vector operands. -- static const bool supports_generic_vector_operands = false; -- - static constexpr bool isSimpleConstant64(jlong value) { - // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. - // Probably always true, even if a temp register is required. -@@ -127,31 +117,6 @@ - // the relevant 32 bits. - static const bool int_in_long = true; - -- // Does the CPU supports vector variable shift instructions? -- static constexpr bool supports_vector_variable_shifts(void) { -- return false; -- } -- -- // Does the CPU supports vector variable rotate instructions? -- static constexpr bool supports_vector_variable_rotates(void) { -- return false; -- } -- -- // Does the CPU supports vector constant rotate instructions? -- static constexpr bool supports_vector_constant_rotates(int shift) { -- return false; -- } -- -- // Does the CPU supports vector unsigned comparison instructions? -- static const bool supports_vector_comparison_unsigned(int vlen, BasicType bt) { -- return false; -- } -- -- // Some microarchitectures have mask registers used on vectors -- static const bool has_predicated_vectors(void) { -- return false; -- } -- - // true means we have fast l2f convers - // false means that conversion is done by runtime call - static constexpr bool convL2FSupported(void) { -@@ -161,9 +126,4 @@ - // Implements a variant of EncodeISOArrayNode that encode ASCII only - static const bool supports_encode_ascii_array = false; - -- // Returns pre-selection estimated size of a vector operation. -- static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { -- return 0; -- } -- - #endif // CPU_RISCV_MATCHER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/register_riscv.cpp b/src/hotspot/cpu/riscv/register_riscv.cpp -index f8116e9df8c..96cf1996a83 100644 ---- a/src/hotspot/cpu/riscv/register_riscv.cpp -+++ b/src/hotspot/cpu/riscv/register_riscv.cpp -@@ -37,11 +37,6 @@ const int ConcreteRegisterImpl::max_fpr = - ConcreteRegisterImpl::max_gpr + - FloatRegisterImpl::number_of_registers * FloatRegisterImpl::max_slots_per_register; - --const int ConcreteRegisterImpl::max_vpr = -- ConcreteRegisterImpl::max_fpr + -- VectorRegisterImpl::number_of_registers * VectorRegisterImpl::max_slots_per_register; -- -- - const char* RegisterImpl::name() const { - static const char *const names[number_of_registers] = { - "zr", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "fp", "x9", -diff --git a/src/hotspot/cpu/riscv/register_riscv.hpp b/src/hotspot/cpu/riscv/register_riscv.hpp -index a9200cac647..d697751f55f 100644 ---- a/src/hotspot/cpu/riscv/register_riscv.hpp -+++ b/src/hotspot/cpu/riscv/register_riscv.hpp -@@ -307,14 +307,12 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { - // it's optoregs. - - number_of_registers = (RegisterImpl::max_slots_per_register * RegisterImpl::number_of_registers + -- FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers + -- VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers) -+ FloatRegisterImpl::max_slots_per_register * FloatRegisterImpl::number_of_registers) - }; - - // added to make it compile - static const int max_gpr; - static const int max_fpr; -- static const int max_vpr; - }; - - typedef AbstractRegSet RegSet; -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 588887e1d96..85593a942e9 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -226,177 +226,6 @@ reg_def F30_H ( SOC, SOC, Op_RegF, 30, f30->as_VMReg()->next() ); - reg_def F31 ( SOC, SOC, Op_RegF, 31, f31->as_VMReg() ); - reg_def F31_H ( SOC, SOC, Op_RegF, 31, f31->as_VMReg()->next() ); - --// ---------------------------- --// Vector Registers --// ---------------------------- -- --// For RVV vector registers, we simply extend vector register size to 4 --// 'logical' slots. This is nominally 128 bits but it actually covers --// all possible 'physical' RVV vector register lengths from 128 ~ 1024 --// bits. The 'physical' RVV vector register length is detected during --// startup, so the register allocator is able to identify the correct --// number of bytes needed for an RVV spill/unspill. -- --reg_def V0 ( SOC, SOC, Op_VecA, 0, v0->as_VMReg() ); --reg_def V0_H ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next() ); --reg_def V0_J ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(2) ); --reg_def V0_K ( SOC, SOC, Op_VecA, 0, v0->as_VMReg()->next(3) ); -- --reg_def V1 ( SOC, SOC, Op_VecA, 1, v1->as_VMReg() ); --reg_def V1_H ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next() ); --reg_def V1_J ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(2) ); --reg_def V1_K ( SOC, SOC, Op_VecA, 1, v1->as_VMReg()->next(3) ); -- --reg_def V2 ( SOC, SOC, Op_VecA, 2, v2->as_VMReg() ); --reg_def V2_H ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next() ); --reg_def V2_J ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(2) ); --reg_def V2_K ( SOC, SOC, Op_VecA, 2, v2->as_VMReg()->next(3) ); -- --reg_def V3 ( SOC, SOC, Op_VecA, 3, v3->as_VMReg() ); --reg_def V3_H ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next() ); --reg_def V3_J ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(2) ); --reg_def V3_K ( SOC, SOC, Op_VecA, 3, v3->as_VMReg()->next(3) ); -- --reg_def V4 ( SOC, SOC, Op_VecA, 4, v4->as_VMReg() ); --reg_def V4_H ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next() ); --reg_def V4_J ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(2) ); --reg_def V4_K ( SOC, SOC, Op_VecA, 4, v4->as_VMReg()->next(3) ); -- --reg_def V5 ( SOC, SOC, Op_VecA, 5, v5->as_VMReg() ); --reg_def V5_H ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next() ); --reg_def V5_J ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(2) ); --reg_def V5_K ( SOC, SOC, Op_VecA, 5, v5->as_VMReg()->next(3) ); -- --reg_def V6 ( SOC, SOC, Op_VecA, 6, v6->as_VMReg() ); --reg_def V6_H ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next() ); --reg_def V6_J ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(2) ); --reg_def V6_K ( SOC, SOC, Op_VecA, 6, v6->as_VMReg()->next(3) ); -- --reg_def V7 ( SOC, SOC, Op_VecA, 7, v7->as_VMReg() ); --reg_def V7_H ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next() ); --reg_def V7_J ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(2) ); --reg_def V7_K ( SOC, SOC, Op_VecA, 7, v7->as_VMReg()->next(3) ); -- --reg_def V8 ( SOC, SOC, Op_VecA, 8, v8->as_VMReg() ); --reg_def V8_H ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next() ); --reg_def V8_J ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(2) ); --reg_def V8_K ( SOC, SOC, Op_VecA, 8, v8->as_VMReg()->next(3) ); -- --reg_def V9 ( SOC, SOC, Op_VecA, 9, v9->as_VMReg() ); --reg_def V9_H ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next() ); --reg_def V9_J ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(2) ); --reg_def V9_K ( SOC, SOC, Op_VecA, 9, v9->as_VMReg()->next(3) ); -- --reg_def V10 ( SOC, SOC, Op_VecA, 10, v10->as_VMReg() ); --reg_def V10_H ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next() ); --reg_def V10_J ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(2) ); --reg_def V10_K ( SOC, SOC, Op_VecA, 10, v10->as_VMReg()->next(3) ); -- --reg_def V11 ( SOC, SOC, Op_VecA, 11, v11->as_VMReg() ); --reg_def V11_H ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next() ); --reg_def V11_J ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(2) ); --reg_def V11_K ( SOC, SOC, Op_VecA, 11, v11->as_VMReg()->next(3) ); -- --reg_def V12 ( SOC, SOC, Op_VecA, 12, v12->as_VMReg() ); --reg_def V12_H ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next() ); --reg_def V12_J ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(2) ); --reg_def V12_K ( SOC, SOC, Op_VecA, 12, v12->as_VMReg()->next(3) ); -- --reg_def V13 ( SOC, SOC, Op_VecA, 13, v13->as_VMReg() ); --reg_def V13_H ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next() ); --reg_def V13_J ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(2) ); --reg_def V13_K ( SOC, SOC, Op_VecA, 13, v13->as_VMReg()->next(3) ); -- --reg_def V14 ( SOC, SOC, Op_VecA, 14, v14->as_VMReg() ); --reg_def V14_H ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next() ); --reg_def V14_J ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(2) ); --reg_def V14_K ( SOC, SOC, Op_VecA, 14, v14->as_VMReg()->next(3) ); -- --reg_def V15 ( SOC, SOC, Op_VecA, 15, v15->as_VMReg() ); --reg_def V15_H ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next() ); --reg_def V15_J ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(2) ); --reg_def V15_K ( SOC, SOC, Op_VecA, 15, v15->as_VMReg()->next(3) ); -- --reg_def V16 ( SOC, SOC, Op_VecA, 16, v16->as_VMReg() ); --reg_def V16_H ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next() ); --reg_def V16_J ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(2) ); --reg_def V16_K ( SOC, SOC, Op_VecA, 16, v16->as_VMReg()->next(3) ); -- --reg_def V17 ( SOC, SOC, Op_VecA, 17, v17->as_VMReg() ); --reg_def V17_H ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next() ); --reg_def V17_J ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(2) ); --reg_def V17_K ( SOC, SOC, Op_VecA, 17, v17->as_VMReg()->next(3) ); -- --reg_def V18 ( SOC, SOC, Op_VecA, 18, v18->as_VMReg() ); --reg_def V18_H ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next() ); --reg_def V18_J ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(2) ); --reg_def V18_K ( SOC, SOC, Op_VecA, 18, v18->as_VMReg()->next(3) ); -- --reg_def V19 ( SOC, SOC, Op_VecA, 19, v19->as_VMReg() ); --reg_def V19_H ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next() ); --reg_def V19_J ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(2) ); --reg_def V19_K ( SOC, SOC, Op_VecA, 19, v19->as_VMReg()->next(3) ); -- --reg_def V20 ( SOC, SOC, Op_VecA, 20, v20->as_VMReg() ); --reg_def V20_H ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next() ); --reg_def V20_J ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(2) ); --reg_def V20_K ( SOC, SOC, Op_VecA, 20, v20->as_VMReg()->next(3) ); -- --reg_def V21 ( SOC, SOC, Op_VecA, 21, v21->as_VMReg() ); --reg_def V21_H ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next() ); --reg_def V21_J ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(2) ); --reg_def V21_K ( SOC, SOC, Op_VecA, 21, v21->as_VMReg()->next(3) ); -- --reg_def V22 ( SOC, SOC, Op_VecA, 22, v22->as_VMReg() ); --reg_def V22_H ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next() ); --reg_def V22_J ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(2) ); --reg_def V22_K ( SOC, SOC, Op_VecA, 22, v22->as_VMReg()->next(3) ); -- --reg_def V23 ( SOC, SOC, Op_VecA, 23, v23->as_VMReg() ); --reg_def V23_H ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next() ); --reg_def V23_J ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(2) ); --reg_def V23_K ( SOC, SOC, Op_VecA, 23, v23->as_VMReg()->next(3) ); -- --reg_def V24 ( SOC, SOC, Op_VecA, 24, v24->as_VMReg() ); --reg_def V24_H ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next() ); --reg_def V24_J ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(2) ); --reg_def V24_K ( SOC, SOC, Op_VecA, 24, v24->as_VMReg()->next(3) ); -- --reg_def V25 ( SOC, SOC, Op_VecA, 25, v25->as_VMReg() ); --reg_def V25_H ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next() ); --reg_def V25_J ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(2) ); --reg_def V25_K ( SOC, SOC, Op_VecA, 25, v25->as_VMReg()->next(3) ); -- --reg_def V26 ( SOC, SOC, Op_VecA, 26, v26->as_VMReg() ); --reg_def V26_H ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next() ); --reg_def V26_J ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(2) ); --reg_def V26_K ( SOC, SOC, Op_VecA, 26, v26->as_VMReg()->next(3) ); -- --reg_def V27 ( SOC, SOC, Op_VecA, 27, v27->as_VMReg() ); --reg_def V27_H ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next() ); --reg_def V27_J ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(2) ); --reg_def V27_K ( SOC, SOC, Op_VecA, 27, v27->as_VMReg()->next(3) ); -- --reg_def V28 ( SOC, SOC, Op_VecA, 28, v28->as_VMReg() ); --reg_def V28_H ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next() ); --reg_def V28_J ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(2) ); --reg_def V28_K ( SOC, SOC, Op_VecA, 28, v28->as_VMReg()->next(3) ); -- --reg_def V29 ( SOC, SOC, Op_VecA, 29, v29->as_VMReg() ); --reg_def V29_H ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next() ); --reg_def V29_J ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(2) ); --reg_def V29_K ( SOC, SOC, Op_VecA, 29, v29->as_VMReg()->next(3) ); -- --reg_def V30 ( SOC, SOC, Op_VecA, 30, v30->as_VMReg() ); --reg_def V30_H ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next() ); --reg_def V30_J ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(2) ); --reg_def V30_K ( SOC, SOC, Op_VecA, 30, v30->as_VMReg()->next(3) ); -- --reg_def V31 ( SOC, SOC, Op_VecA, 31, v31->as_VMReg() ); --reg_def V31_H ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next() ); --reg_def V31_J ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(2) ); --reg_def V31_K ( SOC, SOC, Op_VecA, 31, v31->as_VMReg()->next(3) ); -- - // ---------------------------- - // Special Registers - // ---------------------------- -@@ -495,42 +324,7 @@ alloc_class chunk1( - F27, F27_H, - ); - --alloc_class chunk2( -- V0, V0_H, V0_J, V0_K, -- V1, V1_H, V1_J, V1_K, -- V2, V2_H, V2_J, V2_K, -- V3, V3_H, V3_J, V3_K, -- V4, V4_H, V4_J, V4_K, -- V5, V5_H, V5_J, V5_K, -- V6, V6_H, V6_J, V6_K, -- V7, V7_H, V7_J, V7_K, -- V8, V8_H, V8_J, V8_K, -- V9, V9_H, V9_J, V9_K, -- V10, V10_H, V10_J, V10_K, -- V11, V11_H, V11_J, V11_K, -- V12, V12_H, V12_J, V12_K, -- V13, V13_H, V13_J, V13_K, -- V14, V14_H, V14_J, V14_K, -- V15, V15_H, V15_J, V15_K, -- V16, V16_H, V16_J, V16_K, -- V17, V17_H, V17_J, V17_K, -- V18, V18_H, V18_J, V18_K, -- V19, V19_H, V19_J, V19_K, -- V20, V20_H, V20_J, V20_K, -- V21, V21_H, V21_J, V21_K, -- V22, V22_H, V22_J, V22_K, -- V23, V23_H, V23_J, V23_K, -- V24, V24_H, V24_J, V24_K, -- V25, V25_H, V25_J, V25_K, -- V26, V26_H, V26_J, V26_K, -- V27, V27_H, V27_J, V27_K, -- V28, V28_H, V28_J, V28_K, -- V29, V29_H, V29_J, V29_K, -- V30, V30_H, V30_J, V30_K, -- V31, V31_H, V31_J, V31_K, --); -- --alloc_class chunk3(RFLAGS); -+alloc_class chunk2(RFLAGS); - - //----------Architecture Description Register Classes-------------------------- - // Several register classes are automatically defined based upon information in -@@ -826,41 +620,6 @@ reg_class double_reg( - F31, F31_H - ); - --// Class for all RVV vector registers --reg_class vectora_reg( -- V1, V1_H, V1_J, V1_K, -- V2, V2_H, V2_J, V2_K, -- V3, V3_H, V3_J, V3_K, -- V4, V4_H, V4_J, V4_K, -- V5, V5_H, V5_J, V5_K, -- V6, V6_H, V6_J, V6_K, -- V7, V7_H, V7_J, V7_K, -- V8, V8_H, V8_J, V8_K, -- V9, V9_H, V9_J, V9_K, -- V10, V10_H, V10_J, V10_K, -- V11, V11_H, V11_J, V11_K, -- V12, V12_H, V12_J, V12_K, -- V13, V13_H, V13_J, V13_K, -- V14, V14_H, V14_J, V14_K, -- V15, V15_H, V15_J, V15_K, -- V16, V16_H, V16_J, V16_K, -- V17, V17_H, V17_J, V17_K, -- V18, V18_H, V18_J, V18_K, -- V19, V19_H, V19_J, V19_K, -- V20, V20_H, V20_J, V20_K, -- V21, V21_H, V21_J, V21_K, -- V22, V22_H, V22_J, V22_K, -- V23, V23_H, V23_J, V23_K, -- V24, V24_H, V24_J, V24_K, -- V25, V25_H, V25_J, V25_K, -- V26, V26_H, V26_J, V26_K, -- V27, V27_H, V27_J, V27_K, -- V28, V28_H, V28_J, V28_K, -- V29, V29_H, V29_J, V29_K, -- V30, V30_H, V30_J, V30_K, -- V31, V31_H, V31_J, V31_K --); -- - // Class for 64 bit register f0 - reg_class f0_reg( - F0, F0_H -@@ -881,31 +640,6 @@ reg_class f3_reg( - F3, F3_H - ); - --// class for vector register v1 --reg_class v1_reg( -- V1, V1_H, V1_J, V1_K --); -- --// class for vector register v2 --reg_class v2_reg( -- V2, V2_H, V2_J, V2_K --); -- --// class for vector register v3 --reg_class v3_reg( -- V3, V3_H, V3_J, V3_K --); -- --// class for vector register v4 --reg_class v4_reg( -- V4, V4_H, V4_J, V4_K --); -- --// class for vector register v5 --reg_class v5_reg( -- V5, V5_H, V5_J, V5_K --); -- - // class for condition codes - reg_class reg_flags(RFLAGS); - %} -@@ -1447,7 +1181,7 @@ const Pipeline * MachEpilogNode::pipeline() const { - - // Figure out which register class each belongs in: rc_int, rc_float or - // rc_stack. --enum RC { rc_bad, rc_int, rc_float, rc_vector, rc_stack }; -+enum RC { rc_bad, rc_int, rc_float, rc_stack }; - - static enum RC rc_class(OptoReg::Name reg) { - -@@ -1468,13 +1202,7 @@ static enum RC rc_class(OptoReg::Name reg) { - return rc_float; - } - -- // we have 32 vector register * 4 halves -- int slots_of_vector_registers = VectorRegisterImpl::max_slots_per_register * VectorRegisterImpl::number_of_registers; -- if (reg < slots_of_int_registers + slots_of_float_registers + slots_of_vector_registers) { -- return rc_vector; -- } -- -- // Between vector regs & stack is the flags regs. -+ // Between float regs & stack is the flags regs. - assert(OptoReg::is_stack(reg), "blow up if spilling flags"); - - return rc_stack; -@@ -1512,30 +1240,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo - int src_offset = ra_->reg2offset(src_lo); - int dst_offset = ra_->reg2offset(dst_lo); - -- if (bottom_type()->isa_vect() != NULL) { -- uint ireg = ideal_reg(); -- if (ireg == Op_VecA && cbuf) { -- C2_MacroAssembler _masm(cbuf); -- Assembler::CompressibleRegion cr(&_masm); -- int vector_reg_size_in_bytes = Matcher::scalable_vector_reg_size(T_BYTE); -- if (src_lo_rc == rc_stack && dst_lo_rc == rc_stack) { -- // stack to stack -- __ spill_copy_vector_stack_to_stack(src_offset, dst_offset, -- vector_reg_size_in_bytes); -- } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_stack) { -- // vpr to stack -- __ spill(as_VectorRegister(Matcher::_regEncode[src_lo]), ra_->reg2offset(dst_lo)); -- } else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vector) { -- // stack to vpr -- __ unspill(as_VectorRegister(Matcher::_regEncode[dst_lo]), ra_->reg2offset(src_lo)); -- } else if (src_lo_rc == rc_vector && dst_lo_rc == rc_vector) { -- // vpr to vpr -- __ vmv1r_v(as_VectorRegister(Matcher::_regEncode[dst_lo]), as_VectorRegister(Matcher::_regEncode[src_lo])); -- } else { -- ShouldNotReachHere(); -- } -- } -- } else if (cbuf != NULL) { -+ if (cbuf != NULL) { - C2_MacroAssembler _masm(cbuf); - Assembler::CompressibleRegion cr(&_masm); - switch (src_lo_rc) { -@@ -1619,17 +1324,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo - } else { - st->print("%s", Matcher::regName[dst_lo]); - } -- if (bottom_type()->isa_vect() != NULL) { -- int vsize = 0; -- if (ideal_reg() == Op_VecA) { -- vsize = Matcher::scalable_vector_reg_size(T_BYTE) * 8; -- } else { -- ShouldNotReachHere(); -- } -- st->print("\t# vector spill size = %d", vsize); -- } else { -- st->print("\t# spill size = %d", is64 ? 64 : 32); -- } -+ st->print("\t# spill size = %d", is64 ? 64 : 32); - } - - return 0; -@@ -1796,14 +1491,6 @@ const bool Matcher::match_rule_supported(int opcode) { - } - break; - -- case Op_StrCompressedCopy: // fall through -- case Op_StrInflatedCopy: // fall through -- case Op_CountPositives: -- return UseRVV; -- -- case Op_EncodeISOArray: -- return UseRVV && SpecialEncodeISOArray; -- - case Op_PopCountI: - case Op_PopCountL: - return UsePopCountInstruction; -@@ -1821,37 +1508,15 @@ const bool Matcher::match_rule_supported(int opcode) { - } - - // Identify extra cases that we might want to provide match rules for vector nodes and --// other intrinsics guarded with vector length (vlen) and element type (bt). --const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType bt) { -- if (!match_rule_supported(opcode) || !vector_size_supported(bt, vlen)) { -- return false; -- } -- -- return op_vec_supported(opcode); --} -- --const bool Matcher::match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt) { -+// other intrinsics guarded with vector length (vlen). -+const bool Matcher::match_rule_supported_vector(int opcode, int vlen) { - return false; - } - --const RegMask* Matcher::predicate_reg_mask(void) { -- return NULL; --} -- --const TypeVectMask* Matcher::predicate_reg_type(const Type* elemTy, int length) { -- return NULL; --} -- --// Vector calling convention not yet implemented. --const bool Matcher::supports_vector_calling_convention(void) { -+const bool Matcher::has_predicated_vectors(void) { - return false; - } - --OptoRegPair Matcher::vector_return_value(uint ideal_reg) { -- Unimplemented(); -- return OptoRegPair(0, 0); --} -- - // Is this branch offset short enough that a short branch can be used? - // - // NOTE: If the platform does not provide any short branch variants, then -@@ -1877,11 +1542,6 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { - - // Vector width in bytes. - const int Matcher::vector_width_in_bytes(BasicType bt) { -- if (UseRVV) { -- // The MaxVectorSize should have been set by detecting RVV max vector register size when check UseRVV. -- // MaxVectorSize == VM_Version::_initial_vector_length -- return MaxVectorSize; -- } - return 0; - } - -@@ -1895,34 +1555,10 @@ const int Matcher::min_vector_size(const BasicType bt) { - - // Vector ideal reg. - const uint Matcher::vector_ideal_reg(int len) { -- assert(MaxVectorSize >= len, ""); -- if (UseRVV) { -- return Op_VecA; -- } -- - ShouldNotReachHere(); - return 0; - } - --const int Matcher::scalable_vector_reg_size(const BasicType bt) { -- return Matcher::max_vector_size(bt); --} -- --MachOper* Matcher::pd_specialize_generic_vector_operand(MachOper* original_opnd, uint ideal_reg, bool is_temp) { -- ShouldNotReachHere(); // generic vector operands not supported -- return NULL; --} -- --bool Matcher::is_reg2reg_move(MachNode* m) { -- ShouldNotReachHere(); // generic vector operands not supported -- return false; --} -- --bool Matcher::is_generic_vector(MachOper* opnd) { -- ShouldNotReachHere(); // generic vector operands not supported -- return false; --} -- - // Return whether or not this register is ever used as an argument. - // This function is used on startup to build the trampoline stubs in - // generateOptoStub. Registers not mentioned will be killed by the VM -@@ -3384,67 +3020,6 @@ operand fRegD() - interface(REG_INTER); - %} - --// Generic vector class. This will be used for --// all vector operands. --operand vReg() --%{ -- constraint(ALLOC_IN_RC(vectora_reg)); -- match(VecA); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- --operand vReg_V1() --%{ -- constraint(ALLOC_IN_RC(v1_reg)); -- match(VecA); -- match(vReg); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- --operand vReg_V2() --%{ -- constraint(ALLOC_IN_RC(v2_reg)); -- match(VecA); -- match(vReg); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- --operand vReg_V3() --%{ -- constraint(ALLOC_IN_RC(v3_reg)); -- match(VecA); -- match(vReg); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- --operand vReg_V4() --%{ -- constraint(ALLOC_IN_RC(v4_reg)); -- match(VecA); -- match(vReg); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- --operand vReg_V5() --%{ -- constraint(ALLOC_IN_RC(v5_reg)); -- match(VecA); -- match(vReg); -- op_cost(0); -- format %{ %} -- interface(REG_INTER); --%} -- - // Java Thread Register - operand javaThread_RegP(iRegP reg) - %{ -@@ -7939,17 +7514,6 @@ instruct castDD(fRegD dst) - ins_pipe(pipe_class_empty); - %} - --instruct castVV(vReg dst) --%{ -- match(Set dst (CastVV dst)); -- -- size(0); -- format %{ "# castVV of $dst" %} -- ins_encode(/* empty encoding */); -- ins_cost(0); -- ins_pipe(pipe_class_empty); --%} -- - // ============================================================================ - // Convert Instructions - -@@ -10076,7 +9640,7 @@ instruct partialSubtypeCheckVsZero(iRegP_R15 result, iRegP_R14 sub, iRegP_R10 su - instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, - iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); -+ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); - match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); - effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - -@@ -10094,7 +9658,7 @@ instruct string_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R - instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, - iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); -+ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); - match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); - effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - -@@ -10111,7 +9675,7 @@ instruct string_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R - instruct string_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, - iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); -+ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); - match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); - effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - -@@ -10129,7 +9693,7 @@ instruct string_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_ - iRegI_R10 result, iRegP_R28 tmp1, iRegL_R29 tmp2, iRegL_R30 tmp3, - rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); -+ predicate(((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); - match(Set result (StrComp(Binary str1 cnt1)(Binary str2 cnt2))); - effect(KILL tmp1, KILL tmp2, KILL tmp3, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr); - -@@ -10275,7 +9839,7 @@ instruct stringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) - %{ - match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); -+ predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U); - effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - -@@ -10294,7 +9858,7 @@ instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) - %{ - match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- predicate(!UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); -+ predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L); - effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - -@@ -10310,7 +9874,6 @@ instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, - // clearing of an array - instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy) - %{ -- predicate(!UseRVV); - match(Set dummy (ClearArray cnt base)); - effect(USE_KILL cnt, USE_KILL base); - -@@ -10330,8 +9893,7 @@ instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy) - - instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg cr) - %{ -- predicate(!UseRVV && (uint64_t)n->in(2)->get_long() -- < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)); -+ predicate((uint64_t)n->in(2)->get_long() < (uint64_t)(BlockZeroingLowLimit >> LogBytesPerWord)); - match(Set dummy (ClearArray cnt base)); - effect(USE_KILL base, KILL cr); - -@@ -10348,7 +9910,7 @@ instruct clearArray_imm_reg(immL cnt, iRegP_R28 base, Universe dummy, rFlagsReg - instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, - iRegI_R10 result, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); -+ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); - match(Set result (StrEquals (Binary str1 str2) cnt)); - effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); - -@@ -10364,7 +9926,7 @@ instruct string_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, - instruct string_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, - iRegI_R10 result, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); -+ predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); - match(Set result (StrEquals (Binary str1 str2) cnt)); - effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); - -@@ -10381,7 +9943,7 @@ instruct array_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, - iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, - iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); -+ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); - match(Set result (AryEq ary1 ary2)); - effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); - -@@ -10398,7 +9960,7 @@ instruct array_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, - iRegP_R13 tmp1, iRegP_R14 tmp2, iRegP_R15 tmp3, - iRegP_R16 tmp4, iRegP_R28 tmp5, rFlagsReg cr) - %{ -- predicate(!UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); -+ predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); - match(Set result (AryEq ary1 ary2)); - effect(USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL tmp5, KILL cr); - -diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad -deleted file mode 100644 -index 3828e096b21..00000000000 ---- a/src/hotspot/cpu/riscv/riscv_v.ad -+++ /dev/null -@@ -1,2065 +0,0 @@ --// --// Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. --// Copyright (c) 2020, Arm Limited. All rights reserved. --// Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. --// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. --// --// 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. --// --// -- --// RISCV Vector Extension Architecture Description File -- --opclass vmemA(indirect); -- --source_hpp %{ -- bool op_vec_supported(int opcode); --%} -- --source %{ -- -- static void loadStore(C2_MacroAssembler masm, bool is_store, -- VectorRegister reg, BasicType bt, Register base) { -- Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -- masm.vsetvli(t0, x0, sew); -- if (is_store) { -- masm.vsex_v(reg, base, sew); -- } else { -- masm.vlex_v(reg, base, sew); -- } -- } -- -- bool op_vec_supported(int opcode) { -- switch (opcode) { -- // No multiply reduction instructions -- case Op_MulReductionVD: -- case Op_MulReductionVF: -- case Op_MulReductionVI: -- case Op_MulReductionVL: -- // Others -- case Op_Extract: -- case Op_ExtractB: -- case Op_ExtractC: -- case Op_ExtractD: -- case Op_ExtractF: -- case Op_ExtractI: -- case Op_ExtractL: -- case Op_ExtractS: -- case Op_ExtractUB: -- // Vector API specific -- case Op_AndReductionV: -- case Op_OrReductionV: -- case Op_XorReductionV: -- case Op_LoadVectorGather: -- case Op_StoreVectorScatter: -- case Op_VectorBlend: -- case Op_VectorCast: -- case Op_VectorCastB2X: -- case Op_VectorCastD2X: -- case Op_VectorCastF2X: -- case Op_VectorCastI2X: -- case Op_VectorCastL2X: -- case Op_VectorCastS2X: -- case Op_VectorInsert: -- case Op_VectorLoadConst: -- case Op_VectorLoadMask: -- case Op_VectorLoadShuffle: -- case Op_VectorMaskCmp: -- case Op_VectorRearrange: -- case Op_VectorReinterpret: -- case Op_VectorStoreMask: -- case Op_VectorTest: -- return false; -- default: -- return UseRVV; -- } -- } -- --%} -- --definitions %{ -- int_def VEC_COST (200, 200); --%} -- --// All VEC instructions -- --// vector load/store --instruct loadV(vReg dst, vmemA mem) %{ -- match(Set dst (LoadVector mem)); -- ins_cost(VEC_COST); -- format %{ "vle $dst, $mem\t#@loadV" %} -- ins_encode %{ -- VectorRegister dst_reg = as_VectorRegister($dst$$reg); -- loadStore(C2_MacroAssembler(&cbuf), false, dst_reg, -- Matcher::vector_element_basic_type(this), as_Register($mem$$base)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct storeV(vReg src, vmemA mem) %{ -- match(Set mem (StoreVector mem src)); -- ins_cost(VEC_COST); -- format %{ "vse $src, $mem\t#@storeV" %} -- ins_encode %{ -- VectorRegister src_reg = as_VectorRegister($src$$reg); -- loadStore(C2_MacroAssembler(&cbuf), true, src_reg, -- Matcher::vector_element_basic_type(this, $src), as_Register($mem$$base)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector abs -- --instruct vabsB(vReg dst, vReg src, vReg tmp) %{ -- match(Set dst (AbsVB src)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vrsub.vi $tmp, 0, $src\t#@vabsB\n\t" -- "vmax.vv $dst, $tmp, $src" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -- __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vabsS(vReg dst, vReg src, vReg tmp) %{ -- match(Set dst (AbsVS src)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vrsub.vi $tmp, 0, $src\t#@vabsS\n\t" -- "vmax.vv $dst, $tmp, $src" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -- __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vabsI(vReg dst, vReg src, vReg tmp) %{ -- match(Set dst (AbsVI src)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vrsub.vi $tmp, 0, $src\t#@vabsI\n\t" -- "vmax.vv $dst, $tmp, $src" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -- __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vabsL(vReg dst, vReg src, vReg tmp) %{ -- match(Set dst (AbsVL src)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vrsub.vi $tmp, 0, $src\t#@vabsL\n\t" -- "vmax.vv $dst, $tmp, $src" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vrsub_vi(as_VectorRegister($tmp$$reg), 0, as_VectorRegister($src$$reg)); -- __ vmax_vv(as_VectorRegister($dst$$reg), as_VectorRegister($tmp$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vabsF(vReg dst, vReg src) %{ -- match(Set dst (AbsVF src)); -- ins_cost(VEC_COST); -- format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vabsD(vReg dst, vReg src) %{ -- match(Set dst (AbsVD src)); -- ins_cost(VEC_COST); -- format %{ "vfsgnjx.vv $dst, $src, $src, vm\t#@vabsD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfsgnjx_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector add -- --instruct vaddB(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVB src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vadd.vv $dst, $src1, $src2\t#@vaddB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vaddS(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVS src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vadd.vv $dst, $src1, $src2\t#@vaddS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vaddI(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVI src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vadd.vv $dst, $src1, $src2\t#@vaddI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vaddL(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVL src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vadd.vv $dst, $src1, $src2\t#@vaddL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vaddF(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVF src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vaddD(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AddVD src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfadd.vv $dst, $src1, $src2\t#@vaddD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfadd_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector and -- --instruct vand(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (AndV src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vand.vv $dst, $src1, $src2\t#@vand" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vand_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector or -- --instruct vor(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (OrV src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vor.vv $dst, $src1, $src2\t#@vor" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vor_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector xor -- --instruct vxor(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (XorV src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vxor.vv $dst, $src1, $src2\t#@vxor" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vxor_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector float div -- --instruct vdivF(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (DivVF src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfdiv_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vdivD(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (DivVD src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfdiv.vv $dst, $src1, $src2\t#@vdivD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfdiv_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector integer max/min -- --instruct vmax(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && -- n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); -- match(Set dst (MaxV src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmax.vv $dst, $src1, $src2\t#@vmax" %} -- ins_encode %{ -- BasicType bt = Matcher::vector_element_basic_type(this); -- Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -- __ vsetvli(t0, x0, sew); -- __ vmax_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmin(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() != T_FLOAT && -- n->bottom_type()->is_vect()->element_basic_type() != T_DOUBLE); -- match(Set dst (MinV src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmin.vv $dst, $src1, $src2\t#@vmin" %} -- ins_encode %{ -- BasicType bt = Matcher::vector_element_basic_type(this); -- Assembler::SEW sew = Assembler::elemtype_to_sew(bt); -- __ vsetvli(t0, x0, sew); -- __ vmin_vv(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector float-point max/min -- --instruct vmaxF(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -- match(Set dst (MaxV src1 src2)); -- effect(TEMP_DEF dst); -- ins_cost(VEC_COST); -- format %{ "vmaxF $dst, $src1, $src2\t#@vmaxF" %} -- ins_encode %{ -- __ minmax_FD_v(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -- false /* is_double */, false /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmaxD(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -- match(Set dst (MaxV src1 src2)); -- effect(TEMP_DEF dst); -- ins_cost(VEC_COST); -- format %{ "vmaxD $dst, $src1, $src2\t#@vmaxD" %} -- ins_encode %{ -- __ minmax_FD_v(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -- true /* is_double */, false /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vminF(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -- match(Set dst (MinV src1 src2)); -- effect(TEMP_DEF dst); -- ins_cost(VEC_COST); -- format %{ "vminF $dst, $src1, $src2\t#@vminF" %} -- ins_encode %{ -- __ minmax_FD_v(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -- false /* is_double */, true /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vminD(vReg dst, vReg src1, vReg src2) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -- match(Set dst (MinV src1 src2)); -- effect(TEMP_DEF dst); -- ins_cost(VEC_COST); -- format %{ "vminD $dst, $src1, $src2\t#@vminD" %} -- ins_encode %{ -- __ minmax_FD_v(as_VectorRegister($dst$$reg), -- as_VectorRegister($src1$$reg), as_VectorRegister($src2$$reg), -- true /* is_double */, true /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector fmla -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vfmlaF(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVF dst_src1 (Binary src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vfmlaD(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVD dst_src1 (Binary src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vfmacc.vv $dst_src1, $src2, $src3\t#@vfmlaD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector fmls -- --// dst_src1 = dst_src1 + -src2 * src3 --// dst_src1 = dst_src1 + src2 * -src3 --instruct vfmlsF(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVF dst_src1 (Binary (NegVF src2) src3))); -- match(Set dst_src1 (FmaVF dst_src1 (Binary src2 (NegVF src3)))); -- ins_cost(VEC_COST); -- format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 + -src2 * src3 --// dst_src1 = dst_src1 + src2 * -src3 --instruct vfmlsD(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVD dst_src1 (Binary (NegVD src2) src3))); -- match(Set dst_src1 (FmaVD dst_src1 (Binary src2 (NegVD src3)))); -- ins_cost(VEC_COST); -- format %{ "vfnmsac.vv $dst_src1, $src2, $src3\t#@vfmlsD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector fnmla -- --// dst_src1 = -dst_src1 + -src2 * src3 --// dst_src1 = -dst_src1 + src2 * -src3 --instruct vfnmlaF(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary (NegVF src2) src3))); -- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 (NegVF src3)))); -- ins_cost(VEC_COST); -- format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = -dst_src1 + -src2 * src3 --// dst_src1 = -dst_src1 + src2 * -src3 --instruct vfnmlaD(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary (NegVD src2) src3))); -- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 (NegVD src3)))); -- ins_cost(VEC_COST); -- format %{ "vfnmacc.vv $dst_src1, $src2, $src3\t#@vfnmlaD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfnmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector fnmls -- --// dst_src1 = -dst_src1 + src2 * src3 --instruct vfnmlsF(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVF (NegVF dst_src1) (Binary src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = -dst_src1 + src2 * src3 --instruct vfnmlsD(vReg dst_src1, vReg src2, vReg src3) %{ -- predicate(UseFMA); -- match(Set dst_src1 (FmaVD (NegVD dst_src1) (Binary src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vfmsac.vv $dst_src1, $src2, $src3\t#@vfnmlsD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector mla -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vmlaB(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (AddVB dst_src1 (MulVB src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vmlaS(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (AddVS dst_src1 (MulVS src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vmlaI(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (AddVI dst_src1 (MulVI src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 + src2 * src3 --instruct vmlaL(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (AddVL dst_src1 (MulVL src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vmacc.vv $dst_src1, src2, src3\t#@vmlaL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmacc_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector mls -- --// dst_src1 = dst_src1 - src2 * src3 --instruct vmlsB(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (SubVB dst_src1 (MulVB src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 - src2 * src3 --instruct vmlsS(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (SubVS dst_src1 (MulVS src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 - src2 * src3 --instruct vmlsI(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (SubVI dst_src1 (MulVI src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// dst_src1 = dst_src1 - src2 * src3 --instruct vmlsL(vReg dst_src1, vReg src2, vReg src3) %{ -- match(Set dst_src1 (SubVL dst_src1 (MulVL src2 src3))); -- ins_cost(VEC_COST); -- format %{ "vnmsac.vv $dst_src1, src2, src3\t#@vmlsL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vnmsac_vv(as_VectorRegister($dst_src1$$reg), -- as_VectorRegister($src2$$reg), as_VectorRegister($src3$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector mul -- --instruct vmulB(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVB src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmul.vv $dst, $src1, $src2\t#@vmulB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmulS(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVS src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmul.vv $dst, $src1, $src2\t#@vmulS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmulI(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVI src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmul.vv $dst, $src1, $src2\t#@vmulI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmulL(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVL src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vmul.vv $dst, $src1, $src2\t#@vmulL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmulF(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVF src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vmulD(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (MulVD src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfmul.vv $dst, $src1, $src2\t#@vmulD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfmul_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector fneg -- --instruct vnegF(vReg dst, vReg src) %{ -- match(Set dst (NegVF src)); -- ins_cost(VEC_COST); -- format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vnegD(vReg dst, vReg src) %{ -- match(Set dst (NegVD src)); -- ins_cost(VEC_COST); -- format %{ "vfsgnjn.vv $dst, $src, $src\t#@vnegD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfneg_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// popcount vector -- --instruct vpopcountI(iRegINoSp dst, vReg src) %{ -- match(Set dst (PopCountVI src)); -- format %{ "vpopc.m $dst, $src\t#@vpopcountI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vpopc_m(as_Register($dst$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector add reduction -- --instruct reduce_addB(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -- match(Set dst (AddReductionVI src1 src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vmv.s.x $tmp, $src1\t#@reduce_addB\n\t" -- "vredsum.vs $tmp, $src2, $tmp\n\t" -- "vmv.x.s $dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct reduce_addS(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -- match(Set dst (AddReductionVI src1 src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vmv.s.x $tmp, $src1\t#@reduce_addS\n\t" -- "vredsum.vs $tmp, $src2, $tmp\n\t" -- "vmv.x.s $dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct reduce_addI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -- match(Set dst (AddReductionVI src1 src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vmv.s.x $tmp, $src1\t#@reduce_addI\n\t" -- "vredsum.vs $tmp, $src2, $tmp\n\t" -- "vmv.x.s $dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct reduce_addL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -- match(Set dst (AddReductionVL src1 src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vmv.s.x $tmp, $src1\t#@reduce_addL\n\t" -- "vredsum.vs $tmp, $src2, $tmp\n\t" -- "vmv.x.s $dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredsum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct reduce_addF(fRegF src1_dst, vReg src2, vReg tmp) %{ -- match(Set src1_dst (AddReductionVF src1_dst src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addF\n\t" -- "vfredosum.vs $tmp, $src2, $tmp\n\t" -- "vfmv.f.s $src1_dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); -- __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct reduce_addD(fRegD src1_dst, vReg src2, vReg tmp) %{ -- match(Set src1_dst (AddReductionVD src1_dst src2)); -- effect(TEMP tmp); -- ins_cost(VEC_COST); -- format %{ "vfmv.s.f $tmp, $src1_dst\t#@reduce_addD\n\t" -- "vfredosum.vs $tmp, $src2, $tmp\n\t" -- "vfmv.f.s $src1_dst, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfmv_s_f(as_VectorRegister($tmp$$reg), $src1_dst$$FloatRegister); -- __ vfredosum_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp$$reg)); -- __ vfmv_f_s($src1_dst$$FloatRegister, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector integer max reduction --instruct vreduce_maxB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_maxB $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- Label Ldone; -- __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -- __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -- __ bind(Ldone); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_maxS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_maxS $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- Label Ldone; -- __ ble(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -- __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -- __ bind(Ldone); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_maxI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_maxI $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_maxL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_maxL $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredmax_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector integer min reduction --instruct vreduce_minB(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_minB $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- Label Ldone; -- __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -- __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -- __ bind(Ldone); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_minS(iRegINoSp dst, iRegI src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_minS $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($src2$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- Label Ldone; -- __ bge(as_Register($src1$$reg), as_Register($dst$$reg), Ldone); -- __ mv(as_Register($dst$$reg), as_Register($src1$$reg)); -- __ bind(Ldone); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_minI(iRegINoSp dst, iRegIorL2I src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_minI $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_minL(iRegLNoSp dst, iRegL src1, vReg src2, vReg tmp) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_LONG); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP tmp); -- format %{ "vreduce_minL $dst, $src1, $src2, $tmp" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_s_x(as_VectorRegister($tmp$$reg), $src1$$Register); -- __ vredmin_vs(as_VectorRegister($tmp$$reg), as_VectorRegister($src2$$reg), as_VectorRegister($tmp$$reg)); -- __ vmv_x_s($dst$$Register, as_VectorRegister($tmp$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector float max reduction -- --instruct vreduce_maxF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -- format %{ "reduce_maxF $dst, $src1, $src2, $tmp1, $tmp2" %} -- ins_encode %{ -- __ reduce_minmax_FD_v($dst$$FloatRegister, -- $src1$$FloatRegister, as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -- false /* is_double */, false /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_maxD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -- match(Set dst (MaxReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -- format %{ "reduce_maxD $dst, $src1, $src2, $tmp1, $tmp2" %} -- ins_encode %{ -- __ reduce_minmax_FD_v($dst$$FloatRegister, -- $src1$$FloatRegister, as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -- true /* is_double */, false /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector float min reduction -- --instruct vreduce_minF(fRegF dst, fRegF src1, vReg src2, vReg tmp1, vReg tmp2) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -- format %{ "reduce_minF $dst, $src1, $src2, $tmp1, $tmp2" %} -- ins_encode %{ -- __ reduce_minmax_FD_v($dst$$FloatRegister, -- $src1$$FloatRegister, as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -- false /* is_double */, true /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vreduce_minD(fRegD dst, fRegD src1, vReg src2, vReg tmp1, vReg tmp2) %{ -- predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -- match(Set dst (MinReductionV src1 src2)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2); -- format %{ "reduce_minD $dst, $src1, $src2, $tmp1, $tmp2" %} -- ins_encode %{ -- __ reduce_minmax_FD_v($dst$$FloatRegister, -- $src1$$FloatRegister, as_VectorRegister($src2$$reg), -- as_VectorRegister($tmp1$$reg), as_VectorRegister($tmp2$$reg), -- true /* is_double */, true /* is_min */); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector Math.rint, floor, ceil -- --instruct vroundD(vReg dst, vReg src, immI rmode) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); -- match(Set dst (RoundDoubleModeV src rmode)); -- format %{ "vroundD $dst, $src, $rmode" %} -- ins_encode %{ -- switch ($rmode$$constant) { -- case RoundDoubleModeNode::rmode_rint: -- __ csrwi(CSR_FRM, C2_MacroAssembler::rne); -- __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- break; -- case RoundDoubleModeNode::rmode_floor: -- __ csrwi(CSR_FRM, C2_MacroAssembler::rdn); -- __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- break; -- case RoundDoubleModeNode::rmode_ceil: -- __ csrwi(CSR_FRM, C2_MacroAssembler::rup); -- __ vfcvt_rtz_x_f_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- break; -- default: -- ShouldNotReachHere(); -- break; -- } -- %} -- ins_pipe(pipe_slow); --%} -- --// vector replicate -- --instruct replicateB(vReg dst, iRegIorL2I src) %{ -- match(Set dst (ReplicateB src)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.x $dst, $src\t#@replicateB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateS(vReg dst, iRegIorL2I src) %{ -- match(Set dst (ReplicateS src)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.x $dst, $src\t#@replicateS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateI(vReg dst, iRegIorL2I src) %{ -- match(Set dst (ReplicateI src)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.x $dst, $src\t#@replicateI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateL(vReg dst, iRegL src) %{ -- match(Set dst (ReplicateL src)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.x $dst, $src\t#@replicateL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateB_imm5(vReg dst, immI5 con) %{ -- match(Set dst (ReplicateB con)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.i $dst, $con\t#@replicateB_imm5" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateS_imm5(vReg dst, immI5 con) %{ -- match(Set dst (ReplicateS con)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.i $dst, $con\t#@replicateS_imm5" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateI_imm5(vReg dst, immI5 con) %{ -- match(Set dst (ReplicateI con)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.i $dst, $con\t#@replicateI_imm5" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateL_imm5(vReg dst, immL5 con) %{ -- match(Set dst (ReplicateL con)); -- ins_cost(VEC_COST); -- format %{ "vmv.v.i $dst, $con\t#@replicateL_imm5" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_v_i(as_VectorRegister($dst$$reg), $con$$constant); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateF(vReg dst, fRegF src) %{ -- match(Set dst (ReplicateF src)); -- ins_cost(VEC_COST); -- format %{ "vfmv.v.f $dst, $src\t#@replicateF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct replicateD(vReg dst, fRegD src) %{ -- match(Set dst (ReplicateD src)); -- ins_cost(VEC_COST); -- format %{ "vfmv.v.f $dst, $src\t#@replicateD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfmv_v_f(as_VectorRegister($dst$$reg), $src$$FloatRegister); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector shift -- --instruct vasrB(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (RShiftVB src shift)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift 7\t#@vasrB\n\t" -- "vsra.vi $dst, $src, 7, Assembler::v0_t\n\t" -- "vmnot.m v0, v0\n\t" -- "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- // if shift > BitsPerByte - 1, clear the low BitsPerByte - 1 bits -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- BitsPerByte - 1, Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrS(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (RShiftVS src shift)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift, 15\t#@vasrS\n\t" -- "vsra.vi $dst, $src, 15, Assembler::v0_t\n\t" -- "vmnot.m v0, v0\n\t" -- "vsra.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- // if shift > BitsPerShort - 1, clear the low BitsPerShort - 1 bits -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- BitsPerShort - 1, Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrI(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (RShiftVI src shift)); -- ins_cost(VEC_COST); -- format %{ "vsra.vv $dst, $src, $shift\t#@vasrI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrL(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (RShiftVL src shift)); -- ins_cost(VEC_COST); -- format %{ "vsra.vv $dst, $src, $shift\t#@vasrL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vsra_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslB(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (LShiftVB src shift)); -- ins_cost(VEC_COST); -- effect( TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift, 7\t#@vlslB\n\t" -- "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -- "vmnot.m v0, v0\n\t" -- "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- // if shift > BitsPerByte - 1, clear the element -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg), Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslS(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (LShiftVS src shift)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift, 15\t#@vlslS\n\t" -- "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -- "vmnot.m v0, v0\n\t" -- "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- // if shift > BitsPerShort - 1, clear the element -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg), Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslI(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (LShiftVI src shift)); -- ins_cost(VEC_COST); -- format %{ "vsll.vv $dst, $src, $shift\t#@vlslI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslL(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (LShiftVL src shift)); -- ins_cost(VEC_COST); -- format %{ "vsll.vv $dst, $src, $shift\t# vector (D)" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vsll_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrB(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (URShiftVB src shift)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift, 7\t#@vlsrB\n\t" -- "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -- "vmnot.m v0, v0, v0\n\t" -- "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- // if shift > BitsPerByte - 1, clear the element -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerByte - 1); -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg), Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrS(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (URShiftVS src shift)); -- ins_cost(VEC_COST); -- effect(TEMP_DEF dst); -- format %{ "vmsgtu.vi v0, $shift, 15\t#@vlsrS\n\t" -- "vxor.vv $dst, $src, $src, Assembler::v0_t\n\t" -- "vmnot.m v0, v0\n\t" -- "vsll.vv $dst, $src, $shift, Assembler::v0_t" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- // if shift > BitsPerShort - 1, clear the element -- __ vmsgtu_vi(v0, as_VectorRegister($shift$$reg), BitsPerShort - 1); -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg), Assembler::v0_t); -- // otherwise, shift -- __ vmnot_m(v0, v0); -- __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg), Assembler::v0_t); -- %} -- ins_pipe(pipe_slow); --%} -- -- --instruct vlsrI(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (URShiftVI src shift)); -- ins_cost(VEC_COST); -- format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- -- --instruct vlsrL(vReg dst, vReg src, vReg shift) %{ -- match(Set dst (URShiftVL src shift)); -- ins_cost(VEC_COST); -- format %{ "vsrl.vv $dst, $src, $shift\t#@vlsrL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vsrl_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($shift$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrB_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (RShiftVB src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsra.vi $dst, $src, $shift\t#@vasrB_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e8); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- if (con >= BitsPerByte) con = BitsPerByte - 1; -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrS_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (RShiftVS src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsra.vi $dst, $src, $shift\t#@vasrS_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e16); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- if (con >= BitsPerShort) con = BitsPerShort - 1; -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrI_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (RShiftVI src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vasrI_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e32); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vasrL_imm(vReg dst, vReg src, immI shift) %{ -- predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -- match(Set dst (RShiftVL src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vasrL_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e64); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsra_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrB_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (URShiftVB src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrB_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e8); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- if (con >= BitsPerByte) { -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrS_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (URShiftVS src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrS_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e16); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- if (con >= BitsPerShort) { -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrI_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (URShiftVI src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrI_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e32); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlsrL_imm(vReg dst, vReg src, immI shift) %{ -- predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -- match(Set dst (URShiftVL src (RShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsrl.vi $dst, $src, $shift\t#@vlsrL_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e64); -- if (con == 0) { -- __ vor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsrl_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslB_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (LShiftVB src (LShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsll.vi $dst, $src, $shift\t#@vlslB_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e8); -- if (con >= BitsPerByte) { -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslS_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (LShiftVS src (LShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsll.vi $dst, $src, $shift\t#@vlslS_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e16); -- if (con >= BitsPerShort) { -- __ vxor_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), -- as_VectorRegister($src$$reg)); -- return; -- } -- __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslI_imm(vReg dst, vReg src, immI shift) %{ -- match(Set dst (LShiftVI src (LShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsll.vi $dst, $src, $shift\t#@vlslI_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e32); -- __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vlslL_imm(vReg dst, vReg src, immI shift) %{ -- predicate((n->in(2)->in(1)->get_int() & 0x3f) < 32); -- match(Set dst (LShiftVL src (LShiftCntV shift))); -- ins_cost(VEC_COST); -- format %{ "vsll.vi $dst, $src, $shift\t#@vlslL_imm" %} -- ins_encode %{ -- uint32_t con = (unsigned)$shift$$constant & 0x1f; -- __ vsetvli(t0, x0, Assembler::e64); -- __ vsll_vi(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg), con); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vshiftcntB(vReg dst, iRegIorL2I cnt) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_BYTE); -- match(Set dst (LShiftCntV cnt)); -- match(Set dst (RShiftCntV cnt)); -- format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vshiftcntS(vReg dst, iRegIorL2I cnt) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_SHORT || -- n->bottom_type()->is_vect()->element_basic_type() == T_CHAR); -- match(Set dst (LShiftCntV cnt)); -- match(Set dst (RShiftCntV cnt)); -- format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vshiftcntI(vReg dst, iRegIorL2I cnt) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_INT); -- match(Set dst (LShiftCntV cnt)); -- match(Set dst (RShiftCntV cnt)); -- format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vshiftcntL(vReg dst, iRegIorL2I cnt) %{ -- predicate(n->bottom_type()->is_vect()->element_basic_type() == T_LONG); -- match(Set dst (LShiftCntV cnt)); -- match(Set dst (RShiftCntV cnt)); -- format %{ "vmv.v.x $dst, $cnt\t#@vshiftcntL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vmv_v_x(as_VectorRegister($dst$$reg), as_Register($cnt$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector sqrt -- --instruct vsqrtF(vReg dst, vReg src) %{ -- match(Set dst (SqrtVF src)); -- ins_cost(VEC_COST); -- format %{ "vfsqrt.v $dst, $src\t#@vsqrtF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsqrtD(vReg dst, vReg src) %{ -- match(Set dst (SqrtVD src)); -- ins_cost(VEC_COST); -- format %{ "vfsqrt.v $dst, $src\t#@vsqrtD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfsqrt_v(as_VectorRegister($dst$$reg), as_VectorRegister($src$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --// vector sub -- --instruct vsubB(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVB src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vsub.vv $dst, $src1, $src2\t#@vsubB" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e8); -- __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsubS(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVS src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vsub.vv $dst, $src1, $src2\t#@vsubS" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e16); -- __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsubI(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVI src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vsub.vv $dst, $src1, $src2\t#@vsubI" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsubL(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVL src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vsub.vv $dst, $src1, $src2\t#@vsubL" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsubF(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVF src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfsub.vv $dst, $src1, $src2\t@vsubF" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e32); -- __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vsubD(vReg dst, vReg src1, vReg src2) %{ -- match(Set dst (SubVD src1 src2)); -- ins_cost(VEC_COST); -- format %{ "vfsub.vv $dst, $src1, $src2\t#@vsubD" %} -- ins_encode %{ -- __ vsetvli(t0, x0, Assembler::e64); -- __ vfsub_vv(as_VectorRegister($dst$$reg), as_VectorRegister($src1$$reg), -- as_VectorRegister($src2$$reg)); -- %} -- ins_pipe(pipe_slow); --%} -- --instruct vstring_equalsL(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, -- iRegI_R10 result, vReg_V1 v1, -- vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) --%{ -- predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL); -- match(Set result (StrEquals (Binary str1 str2) cnt)); -- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); -- -- format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsL" %} -- ins_encode %{ -- // Count is in 8-bit bytes; non-Compact chars are 16 bits. -- __ string_equals_v($str1$$Register, $str2$$Register, -- $result$$Register, $cnt$$Register, 1); -- %} -- ins_pipe(pipe_class_memory); --%} -- --instruct vstring_equalsU(iRegP_R11 str1, iRegP_R13 str2, iRegI_R14 cnt, -- iRegI_R10 result, vReg_V1 v1, -- vReg_V2 v2, vReg_V3 v3, rFlagsReg cr) --%{ -- predicate(UseRVV && ((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU); -- match(Set result (StrEquals (Binary str1 str2) cnt)); -- effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, TEMP v1, TEMP v2, TEMP v3, KILL cr); -- -- format %{ "String Equals $str1, $str2, $cnt -> $result\t#@string_equalsU" %} -- ins_encode %{ -- // Count is in 8-bit bytes; non-Compact chars are 16 bits. -- __ string_equals_v($str1$$Register, $str2$$Register, -- $result$$Register, $cnt$$Register, 2); -- %} -- ins_pipe(pipe_class_memory); --%} -- --instruct varray_equalsB(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) --%{ -- predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL); -- match(Set result (AryEq ary1 ary2)); -- effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); -- -- format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsB // KILL $tmp" %} -- ins_encode %{ -- __ arrays_equals_v($ary1$$Register, $ary2$$Register, -- $result$$Register, $tmp$$Register, 1); -- %} -- ins_pipe(pipe_class_memory); --%} -- --instruct varray_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegP_R28 tmp, rFlagsReg cr) --%{ -- predicate(UseRVV && ((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU); -- match(Set result (AryEq ary1 ary2)); -- effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP v1, TEMP v2, TEMP v3, KILL cr); -- -- format %{ "Array Equals $ary1, ary2 -> $result\t#@array_equalsC // KILL $tmp" %} -- ins_encode %{ -- __ arrays_equals_v($ary1$$Register, $ary2$$Register, -- $result$$Register, $tmp$$Register, 2); -- %} -- ins_pipe(pipe_class_memory); --%} -- --instruct vstring_compareU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -- iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -- iRegP_R28 tmp1, iRegL_R29 tmp2) --%{ -- predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UU); -- match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -- effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -- TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -- -- format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareU" %} -- ins_encode %{ -- // Count is in 8-bit bytes; non-Compact chars are 16 bits. -- __ string_compare_v($str1$$Register, $str2$$Register, -- $cnt1$$Register, $cnt2$$Register, $result$$Register, -- $tmp1$$Register, $tmp2$$Register, -- StrIntrinsicNode::UU); -- %} -- ins_pipe(pipe_class_memory); --%} --instruct vstring_compareL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -- iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -- iRegP_R28 tmp1, iRegL_R29 tmp2) --%{ -- predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LL); -- match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -- effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -- TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -- -- format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareL" %} -- ins_encode %{ -- __ string_compare_v($str1$$Register, $str2$$Register, -- $cnt1$$Register, $cnt2$$Register, $result$$Register, -- $tmp1$$Register, $tmp2$$Register, -- StrIntrinsicNode::LL); -- %} -- ins_pipe(pipe_class_memory); --%} -- --instruct vstring_compareUL(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -- iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -- iRegP_R28 tmp1, iRegL_R29 tmp2) --%{ -- predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::UL); -- match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -- effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -- TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -- -- format %{"String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareUL" %} -- ins_encode %{ -- __ string_compare_v($str1$$Register, $str2$$Register, -- $cnt1$$Register, $cnt2$$Register, $result$$Register, -- $tmp1$$Register, $tmp2$$Register, -- StrIntrinsicNode::UL); -- %} -- ins_pipe(pipe_class_memory); --%} --instruct vstring_compareLU(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2, -- iRegI_R10 result, vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5, -- iRegP_R28 tmp1, iRegL_R29 tmp2) --%{ -- predicate(UseRVV && ((StrCompNode *)n)->encoding() == StrIntrinsicNode::LU); -- match(Set result(StrComp(Binary str1 cnt1)(Binary str2 cnt2))); -- effect(KILL tmp1, KILL tmp2, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, -- TEMP v1, TEMP v2, TEMP v3, TEMP v4, TEMP v5); -- -- format %{ "String Compare $str1, $cnt1, $str2, $cnt2 -> $result\t#@string_compareLU" %} -- ins_encode %{ -- __ string_compare_v($str1$$Register, $str2$$Register, -- $cnt1$$Register, $cnt2$$Register, $result$$Register, -- $tmp1$$Register, $tmp2$$Register, -- StrIntrinsicNode::LU); -- %} -- ins_pipe(pipe_class_memory); --%} -- --// fast byte[] to char[] inflation --instruct vstring_inflate(Universe dummy, iRegP_R10 src, iRegP_R11 dst, iRegI_R12 len, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) --%{ -- predicate(UseRVV); -- match(Set dummy (StrInflatedCopy src (Binary dst len))); -- effect(TEMP v1, TEMP v2, TEMP v3, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len); -- -- format %{ "String Inflate $src,$dst" %} -- ins_encode %{ -- __ byte_array_inflate_v($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register); -- %} -- ins_pipe(pipe_class_memory); --%} -- --// encode char[] to byte[] in ISO_8859_1 --instruct vencode_iso_array(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) --%{ -- predicate(UseRVV); -- match(Set result (EncodeISOArray src (Binary dst len))); -- effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, -- TEMP v1, TEMP v2, TEMP v3, TEMP tmp); -- -- format %{ "Encode array $src,$dst,$len -> $result" %} -- ins_encode %{ -- __ encode_iso_array_v($src$$Register, $dst$$Register, $len$$Register, -- $result$$Register, $tmp$$Register); -- %} -- ins_pipe( pipe_class_memory ); --%} -- --// fast char[] to byte[] compression --instruct vstring_compress(iRegP_R12 src, iRegP_R11 dst, iRegI_R13 len, iRegI_R10 result, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3, iRegL tmp) --%{ -- predicate(UseRVV); -- match(Set result (StrCompressedCopy src (Binary dst len))); -- effect(TEMP_DEF result, USE_KILL src, USE_KILL dst, USE_KILL len, -- TEMP v1, TEMP v2, TEMP v3, TEMP tmp); -- -- format %{ "String Compress $src,$dst -> $result // KILL R11, R12, R13" %} -- ins_encode %{ -- __ char_array_compress_v($src$$Register, $dst$$Register, $len$$Register, -- $result$$Register, $tmp$$Register); -- %} -- ins_pipe( pipe_slow ); --%} -- --instruct vcount_positives(iRegP_R11 ary, iRegI_R12 len, iRegI_R10 result, iRegL tmp) --%{ -- predicate(UseRVV); -- match(Set result (CountPositives ary len)); -- effect(USE_KILL ary, USE_KILL len, TEMP tmp); -- -- format %{ "count positives byte[] $ary, $len -> $result" %} -- ins_encode %{ -- __ count_positives_v($ary$$Register, $len$$Register, $result$$Register, $tmp$$Register); -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct vstringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -- iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) --%{ -- predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U)); -- match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, -- TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); -- -- format %{ "StringUTF16 IndexOf char[] $str1, $cnt1, $ch -> $result" %} -- -- ins_encode %{ -- __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, -- $result$$Register, $tmp1$$Register, $tmp2$$Register, -- false /* isL */); -- %} -- -- ins_pipe(pipe_class_memory); --%} -- --instruct vstringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -- iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -- vReg_V1 v1, vReg_V2 v2, vReg_V3 v3) --%{ -- predicate(UseRVV && (((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L)); -- match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- effect(TEMP_DEF result, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, -- TEMP tmp1, TEMP tmp2, TEMP v1, TEMP v2, TEMP v3); -- -- format %{ "StringLatin1 IndexOf char[] $str1, $cnt1, $ch -> $result" %} -- -- ins_encode %{ -- __ string_indexof_char_v($str1$$Register, $cnt1$$Register, $ch$$Register, -- $result$$Register, $tmp1$$Register, $tmp2$$Register, -- true /* isL */); -- %} -- -- ins_pipe(pipe_class_memory); --%} -- --// clearing of an array --instruct vclearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy, -- vReg_V1 vReg1, vReg_V2 vReg2, vReg_V3 vReg3) --%{ -- predicate(UseRVV); -- match(Set dummy (ClearArray cnt base)); -- effect(USE_KILL cnt, USE_KILL base, TEMP vReg1, TEMP vReg2, TEMP vReg3); -- -- format %{ "ClearArray $cnt, $base\t#@clearArray_reg_reg" %} -- -- ins_encode %{ -- __ clear_array_v($base$$Register, $cnt$$Register); -- %} -- -- ins_pipe(pipe_class_memory); --%} -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index f85d4b25a76..4daed17df10 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -80,9 +80,8 @@ class SimpleRuntimeFrame { - }; - - class RegisterSaver { -- const bool _save_vectors; - public: -- RegisterSaver(bool save_vectors) : _save_vectors(UseRVV && save_vectors) {} -+ RegisterSaver() {} - ~RegisterSaver() {} - OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); - void restore_live_registers(MacroAssembler* masm); -@@ -91,11 +90,7 @@ class RegisterSaver { - // Used by deoptimization when it is managing result register - // values on its own - // gregs:28, float_register:32; except: x1(ra) & x2(sp) & gp(x3) & tp(x4) -- // |---v0---|<---SP -- // |---v1---|save vectors only in generate_handler_blob -- // |-- .. --| -- // |---v31--|----- -- // |---f0---| -+ // |---f0---|<---SP - // |---f1---| - // | .. | - // |---f31--| -@@ -106,16 +101,8 @@ class RegisterSaver { - // |---x31--| - // |---fp---| - // |---ra---| -- int v0_offset_in_bytes(void) { return 0; } - int f0_offset_in_bytes(void) { -- int f0_offset = 0; --#ifdef COMPILER2 -- if (_save_vectors) { -- f0_offset += Matcher::scalable_vector_reg_size(T_INT) * VectorRegisterImpl::number_of_registers * -- BytesPerInt; -- } --#endif -- return f0_offset; -+ return 0; - } - int reserved_slot_offset_in_bytes(void) { - return f0_offset_in_bytes() + -@@ -142,15 +129,6 @@ class RegisterSaver { - }; - - OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { -- int vector_size_in_bytes = 0; -- int vector_size_in_slots = 0; --#ifdef COMPILER2 -- if (_save_vectors) { -- vector_size_in_bytes += Matcher::scalable_vector_reg_size(T_BYTE); -- vector_size_in_slots += Matcher::scalable_vector_reg_size(T_INT); -- } --#endif -- - assert_cond(masm != NULL && total_frame_words != NULL); - int frame_size_in_bytes = align_up(additional_frame_words * wordSize + ra_offset_in_bytes() + wordSize, 16); - // OopMap frame size is in compiler stack slots (jint's) not bytes or words -@@ -161,9 +139,9 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ - int frame_size_in_words = frame_size_in_bytes / wordSize; - *total_frame_words = frame_size_in_words; - -- // Save Integer, Float and Vector registers. -+ // Save Integer and Float registers. - __ enter(); -- __ push_CPU_state(_save_vectors, vector_size_in_bytes); -+ __ push_CPU_state(); - - // Set an oopmap for the call site. This oopmap will map all - // oop-registers and debug-info registers as callee-saved. This -@@ -176,13 +154,6 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ - - int sp_offset_in_slots = 0; - int step_in_slots = 0; -- if (_save_vectors) { -- step_in_slots = vector_size_in_slots; -- for (int i = 0; i < VectorRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { -- VectorRegister r = as_VectorRegister(i); -- oop_map->set_callee_saved(VMRegImpl::stack2reg(sp_offset_in_slots), r->as_VMReg()); -- } -- } - - step_in_slots = FloatRegisterImpl::max_slots_per_register; - for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++, sp_offset_in_slots += step_in_slots) { -@@ -207,18 +178,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ - - void RegisterSaver::restore_live_registers(MacroAssembler* masm) { - assert_cond(masm != NULL); --#ifdef COMPILER2 -- __ pop_CPU_state(_save_vectors, Matcher::scalable_vector_reg_size(T_BYTE)); --#else -- __ pop_CPU_state(_save_vectors); --#endif -+ __ pop_CPU_state(); - __ leave(); - } - - // Is vector's size (in bytes) bigger than a size saved by default? --// riscv does not ovlerlay the floating-point registers on vector registers like aarch64. - bool SharedRuntime::is_wide_vector(int size) { -- return UseRVV; -+ return false; - } - - // The java_calling_convention describes stack locations as ideal slots on -@@ -674,13 +640,6 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm - return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); - } - --int SharedRuntime::vector_calling_convention(VMRegPair *regs, -- uint num_bits, -- uint total_args_passed) { -- Unimplemented(); -- return 0; --} -- - int SharedRuntime::c_calling_convention(const BasicType *sig_bt, - VMRegPair *regs, - VMRegPair *regs2, -@@ -1891,7 +1850,7 @@ void SharedRuntime::generate_deopt_blob() { - OopMap* map = NULL; - OopMapSet *oop_maps = new OopMapSet(); - assert_cond(masm != NULL && oop_maps != NULL); -- RegisterSaver reg_saver(COMPILER2_OR_JVMCI != 0); -+ RegisterSaver reg_saver; - - // ------------- - // This code enters when returning to a de-optimized nmethod. A return -@@ -2423,7 +2382,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t - address call_pc = NULL; - int frame_size_in_words = -1; - bool cause_return = (poll_type == POLL_AT_RETURN); -- RegisterSaver reg_saver(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); -+ RegisterSaver reg_saver; - - // Save Integer and Float registers. - map = reg_saver.save_live_registers(masm, 0, &frame_size_in_words); -@@ -2542,7 +2501,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha - assert_cond(masm != NULL); - - int frame_size_in_words = -1; -- RegisterSaver reg_saver(false /* save_vectors */); -+ RegisterSaver reg_saver; - - OopMapSet *oop_maps = new OopMapSet(); - assert_cond(oop_maps != NULL); -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index b05edf7172c..39416441bdf 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -2843,111 +2843,6 @@ class StubGenerator: public StubCodeGenerator { - - return entry; - } -- -- // Arguments: -- // -- // Input: -- // c_rarg0 - newArr address -- // c_rarg1 - oldArr address -- // c_rarg2 - newIdx -- // c_rarg3 - shiftCount -- // c_rarg4 - numIter -- // -- address generate_bigIntegerLeftShift() { -- __ align(CodeEntryAlignment); -- StubCodeMark mark(this, "StubRoutines", "bigIntegerLeftShiftWorker"); -- address entry = __ pc(); -- -- Label loop, exit; -- -- Register newArr = c_rarg0; -- Register oldArr = c_rarg1; -- Register newIdx = c_rarg2; -- Register shiftCount = c_rarg3; -- Register numIter = c_rarg4; -- -- Register shiftRevCount = c_rarg5; -- Register oldArrNext = t1; -- -- __ beqz(numIter, exit); -- __ shadd(newArr, newIdx, newArr, t0, 2); -- -- __ li(shiftRevCount, 32); -- __ sub(shiftRevCount, shiftRevCount, shiftCount); -- -- __ bind(loop); -- __ addi(oldArrNext, oldArr, 4); -- __ vsetvli(t0, numIter, Assembler::e32, Assembler::m4); -- __ vle32_v(v0, oldArr); -- __ vle32_v(v4, oldArrNext); -- __ vsll_vx(v0, v0, shiftCount); -- __ vsrl_vx(v4, v4, shiftRevCount); -- __ vor_vv(v0, v0, v4); -- __ vse32_v(v0, newArr); -- __ sub(numIter, numIter, t0); -- __ shadd(oldArr, t0, oldArr, t1, 2); -- __ shadd(newArr, t0, newArr, t1, 2); -- __ bnez(numIter, loop); -- -- __ bind(exit); -- __ ret(); -- -- return entry; -- } -- -- // Arguments: -- // -- // Input: -- // c_rarg0 - newArr address -- // c_rarg1 - oldArr address -- // c_rarg2 - newIdx -- // c_rarg3 - shiftCount -- // c_rarg4 - numIter -- // -- address generate_bigIntegerRightShift() { -- __ align(CodeEntryAlignment); -- StubCodeMark mark(this, "StubRoutines", "bigIntegerRightShiftWorker"); -- address entry = __ pc(); -- -- Label loop, exit; -- -- Register newArr = c_rarg0; -- Register oldArr = c_rarg1; -- Register newIdx = c_rarg2; -- Register shiftCount = c_rarg3; -- Register numIter = c_rarg4; -- Register idx = numIter; -- -- Register shiftRevCount = c_rarg5; -- Register oldArrNext = c_rarg6; -- Register newArrCur = t0; -- Register oldArrCur = t1; -- -- __ beqz(idx, exit); -- __ shadd(newArr, newIdx, newArr, t0, 2); -- -- __ li(shiftRevCount, 32); -- __ sub(shiftRevCount, shiftRevCount, shiftCount); -- -- __ bind(loop); -- __ vsetvli(t0, idx, Assembler::e32, Assembler::m4); -- __ sub(idx, idx, t0); -- __ shadd(oldArrNext, idx, oldArr, t1, 2); -- __ shadd(newArrCur, idx, newArr, t1, 2); -- __ addi(oldArrCur, oldArrNext, 4); -- __ vle32_v(v0, oldArrCur); -- __ vle32_v(v4, oldArrNext); -- __ vsrl_vx(v0, v0, shiftCount); -- __ vsll_vx(v4, v4, shiftRevCount); -- __ vor_vv(v0, v0, v4); -- __ vse32_v(v0, newArrCur); -- __ bnez(idx, loop); -- -- __ bind(exit); -- __ ret(); -- -- return entry; -- } - #endif - - #ifdef COMPILER2 -@@ -3813,11 +3708,6 @@ class StubGenerator: public StubCodeGenerator { - MontgomeryMultiplyGenerator g(_masm, /*squaring*/true); - StubRoutines::_montgomerySquare = g.generate_square(); - } -- -- if (UseRVVForBigIntegerShiftIntrinsics) { -- StubRoutines::_bigIntegerLeftShiftWorker = generate_bigIntegerLeftShift(); -- StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift(); -- } - #endif - - generate_compare_long_strings(); -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index 768c7633ca6..2c15a834542 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -167,10 +167,6 @@ void VM_Version::c2_initialize() { - FLAG_SET_DEFAULT(MaxVectorSize, 0); - } - -- if (!UseRVV) { -- FLAG_SET_DEFAULT(UseRVVForBigIntegerShiftIntrinsics, false); -- } -- - if (UseRVV) { - if (FLAG_IS_DEFAULT(MaxVectorSize)) { - MaxVectorSize = _initial_vector_length; -diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.cpp b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -index aa7222dc64a..1f6eff96cba 100644 ---- a/src/hotspot/cpu/riscv/vmreg_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -@@ -45,16 +45,8 @@ void VMRegImpl::set_regName() { - freg = freg->successor(); - } - -- VectorRegister vreg = ::as_VectorRegister(0); -- for ( ; i < ConcreteRegisterImpl::max_vpr ; ) { -- for (int j = 0 ; j < VectorRegisterImpl::max_slots_per_register ; j++) { -- regName[i++] = reg->name(); -- } -- vreg = vreg->successor(); -- } -- - for ( ; i < ConcreteRegisterImpl::number_of_registers ; i++) { -- regName[i] = "NON-GPR-FPR-VPR"; -+ regName[i] = "NON-GPR-FPR"; - } - } - -diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.hpp b/src/hotspot/cpu/riscv/vmreg_riscv.hpp -index 9e611b1f671..6f613a8f11a 100644 ---- a/src/hotspot/cpu/riscv/vmreg_riscv.hpp -+++ b/src/hotspot/cpu/riscv/vmreg_riscv.hpp -@@ -34,10 +34,6 @@ inline bool is_FloatRegister() { - return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; - } - --inline bool is_VectorRegister() { -- return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_vpr; --} -- - inline Register as_Register() { - assert(is_Register(), "must be"); - return ::as_Register(value() / RegisterImpl::max_slots_per_register); -@@ -49,20 +45,9 @@ inline FloatRegister as_FloatRegister() { - FloatRegisterImpl::max_slots_per_register); - } - --inline VectorRegister as_VectorRegister() { -- assert(is_VectorRegister() && ((value() & (VectorRegisterImpl::max_slots_per_register - 1)) == 0), "must be"); -- return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) / -- VectorRegisterImpl::max_slots_per_register); --} -- - inline bool is_concrete() { - assert(is_reg(), "must be"); -- if (is_VectorRegister()) { -- int base = value() - ConcreteRegisterImpl::max_fpr; -- return (base % VectorRegisterImpl::max_slots_per_register) == 0; -- } else { -- return is_even(value()); -- } -+ return is_even(value()); - } - - #endif // CPU_RISCV_VMREG_RISCV_HPP - -From b2011bad9b7404c1f6d0c1aa3176569d7f07d7a9 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Mon, 27 Mar 2023 16:05:55 +0800 -Subject: [PATCH 004/140] Revert: JDK-8253180: ZGC: Implementation of JEP 376: - ZGC: Concurrent Thread-Stack Processing JDK-8220051: Remove global safepoint - code - ---- - src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 14 ------ - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 14 +++--- - .../riscv/c2_safepointPollStubTable_riscv.cpp | 47 ------------------ - src/hotspot/cpu/riscv/frame_riscv.cpp | 9 +--- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 19 +------- - .../cpu/riscv/macroAssembler_riscv.cpp | 48 +++++++++++-------- - .../cpu/riscv/macroAssembler_riscv.hpp | 5 +- - src/hotspot/cpu/riscv/riscv.ad | 14 ++---- - src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 - - 9 files changed, 45 insertions(+), 127 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp - -diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -index dcd0472c540..af7bd067f33 100644 ---- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -@@ -39,20 +39,6 @@ - - #define __ ce->masm()-> - --void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { -- __ bind(_entry); -- InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset()); -- __ code_section()->relocate(__ pc(), safepoint_pc.rspec()); -- __ la(t0, safepoint_pc.target()); -- __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); -- -- assert(SharedRuntime::polling_page_return_handler_blob() != NULL, -- "polling page return stub not created yet"); -- address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); -- -- __ far_jump(RuntimeAddress(stub)); --} -- - void CounterOverflowStub::emit_code(LIR_Assembler* ce) { - __ bind(_entry); - Metadata *m = _method->as_constant_ptr()->as_metadata(); -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index bba3bd4709c..0e383a3c139 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -424,7 +424,7 @@ int LIR_Assembler::emit_deopt_handler() { - return offset; - } - --void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { -+void LIR_Assembler::return_op(LIR_Opr result) { - assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == x10, "word returns are in x10"); - - // Pop the stack before the safepoint code -@@ -434,18 +434,20 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { - __ reserved_stack_check(); - } - -- code_stub->set_safepoint_offset(__ offset()); -- __ relocate(relocInfo::poll_return_type); -- __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); -+ address polling_page(os::get_polling_page()); -+ __ read_polling_page(t0, polling_page, relocInfo::poll_return_type); - __ ret(); - } - - int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { -+ address polling_page(os::get_polling_page()); - guarantee(info != NULL, "Shouldn't be NULL"); -- __ get_polling_page(t0, relocInfo::poll_type); -+ assert(os::is_poll_address(polling_page), "should be"); -+ int32_t offset = 0; -+ __ get_polling_page(t0, polling_page, offset, relocInfo::poll_type); - add_debug_info_for_branch(info); // This isn't just debug info: - // it's the oop map -- __ read_polling_page(t0, 0, relocInfo::poll_type); -+ __ read_polling_page(t0, offset, relocInfo::poll_type); - return __ offset(); - } - -diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp -deleted file mode 100644 -index a90d9fdc160..00000000000 ---- a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp -+++ /dev/null -@@ -1,47 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#include "precompiled.hpp" --#include "asm/macroAssembler.hpp" --#include "opto/compile.hpp" --#include "opto/node.hpp" --#include "opto/output.hpp" --#include "runtime/sharedRuntime.hpp" -- --#define __ masm. --void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { -- assert(SharedRuntime::polling_page_return_handler_blob() != NULL, -- "polling page return stub not created yet"); -- address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); -- RuntimeAddress callback_addr(stub); -- -- __ bind(entry->_stub_label); -- InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); -- masm.code_section()->relocate(masm.pc(), safepoint_pc.rspec()); -- __ la(t0, safepoint_pc.target()); -- __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); -- __ far_jump(callback_addr); --} --#undef __ -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 6e38960598a..41e52a4d491 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -39,7 +39,6 @@ - #include "runtime/monitorChunk.hpp" - #include "runtime/os.inline.hpp" - #include "runtime/signature.hpp" --#include "runtime/stackWatermarkSet.hpp" - #include "runtime/stubCodeGenerator.hpp" - #include "runtime/stubRoutines.hpp" - #include "vmreg_riscv.inline.hpp" -@@ -509,13 +508,7 @@ frame frame::sender_raw(RegisterMap* map) const { - } - - frame frame::sender(RegisterMap* map) const { -- frame result = sender_raw(map); -- -- if (map->process_frames()) { -- StackWatermarkSet::on_iteration(map->thread(), result); -- } -- -- return result; -+ return sender_raw(map); - } - - bool frame::is_interpreted_frame_valid(JavaThread* thread) const { -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index d12dcb2af19..9090ad0c058 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -519,7 +519,7 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, - - if (needs_thread_local_poll) { - NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); -- ld(t1, Address(xthread, JavaThread::polling_word_offset())); -+ ld(t1, Address(xthread, Thread::polling_page_offset())); - andi(t1, t1, SafepointMechanism::poll_bit()); - bnez(t1, safepoint); - } -@@ -591,23 +591,6 @@ void InterpreterMacroAssembler::remove_activation( - // result check if synchronized method - Label unlocked, unlock, no_unlock; - -- // The below poll is for the stack watermark barrier. It allows fixing up frames lazily, -- // that would normally not be safe to use. Such bad returns into unsafe territory of -- // the stack, will call InterpreterRuntime::at_unwind. -- Label slow_path; -- Label fast_path; -- safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); -- j(fast_path); -- -- bind(slow_path); -- push(state); -- set_last_Java_frame(esp, fp, (address)pc(), t0); -- super_call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::at_unwind), xthread); -- reset_last_Java_frame(true); -- pop(state); -- -- bind(fast_path); -- - // get the value of _do_not_unlock_if_synchronized into x13 - const Address do_not_unlock_if_synchronized(xthread, - in_bytes(JavaThread::do_not_unlock_if_synchronized_offset())); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 8b8d126f6c9..4b6136ae36b 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -2122,15 +2122,16 @@ void MacroAssembler::check_klass_subtype(Register sub_klass, - } - - void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod) { -- ld(t0, Address(xthread, JavaThread::polling_word_offset())); -- if (acquire) { -- membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); -- } -- if (at_return) { -- bgtu(in_nmethod ? sp : fp, t0, slow_path, true /* is_far */); -+ if (SafepointMechanism::uses_thread_local_poll()) { -+ ld(t1, Address(xthread, Thread::polling_page_offset())); -+ andi(t0, t1, SafepointMechanism::poll_bit()); -+ bnez(t0, slow_path); - } else { -- andi(t0, t0, SafepointMechanism::poll_bit()); -- bnez(t0, slow_path, true /* is_far */); -+ int32_t offset = 0; -+ la_patchable(t0, ExternalAddress(SafepointSynchronize::address_of_state()), offset); -+ lwu(t0, Address(t0, offset)); -+ assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code"); -+ bnez(t0, slow_path); - } - } - -@@ -2752,22 +2753,29 @@ void MacroAssembler::reserved_stack_check() { - } - - // Move the address of the polling page into dest. --void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype) { -- ld(dest, Address(xthread, JavaThread::polling_page_offset())); -+void MacroAssembler::get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype) { -+ if (SafepointMechanism::uses_thread_local_poll()) { -+ ld(dest, Address(xthread, Thread::polling_page_offset())); -+ } else { -+ uint64_t align = (uint64_t)page & 0xfff; -+ assert(align == 0, "polling page must be page aligned"); -+ la_patchable(dest, Address(page, rtype), offset); -+ } - } - - // Read the polling page. The address of the polling page must - // already be in r. --address MacroAssembler::read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype) { -- address mark; -- { -- InstructionMark im(this); -- code_section()->relocate(inst_mark(), rtype); -- lwu(zr, Address(r, offset)); -- mark = inst_mark(); -- } -- verify_cross_modify_fence_not_required(); -- return mark; -+void MacroAssembler::read_polling_page(Register dest, address page, relocInfo::relocType rtype) { -+ int32_t offset = 0; -+ get_polling_page(dest, page, offset, rtype); -+ read_polling_page(dest, offset, rtype); -+} -+ -+// Read the polling page. The address of the polling page must -+// already be in r. -+void MacroAssembler::read_polling_page(Register dest, int32_t offset, relocInfo::relocType rtype) { -+ code_section()->relocate(pc(), rtype); -+ lwu(zr, Address(dest, offset)); - } - - void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index b43131514c1..041c696add6 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -625,8 +625,9 @@ class MacroAssembler: public Assembler { - - void reserved_stack_check(); - -- void get_polling_page(Register dest, relocInfo::relocType rtype); -- address read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); -+ void get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype); -+ void read_polling_page(Register r, address page, relocInfo::relocType rtype); -+ void read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); - - address trampoline_call(Address entry, CodeBuffer* cbuf = NULL); - address ic_call(address entry, jint method_index = 0); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 85593a942e9..996fa1fb68f 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1132,9 +1132,9 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - } - - if (do_polling() && C->is_method_compilation()) { -- st->print("# test polling word\n\t"); -- st->print("ld t0, [xthread,#%d]\n\t", in_bytes(JavaThread::polling_word_offset())); -- st->print("bgtu sp, t0, #slow_path"); -+ st->print("# touch polling page\n\t"); -+ st->print("li t0, #0x%lx\n\t", p2i(os::get_polling_page())); -+ st->print("ld zr, [t0]"); - } - } - #endif -@@ -1153,13 +1153,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - } - - if (do_polling() && C->is_method_compilation()) { -- Label dummy_label; -- Label* code_stub = &dummy_label; -- if (!C->output()->in_scratch_emit_size()) { -- code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); -- } -- __ relocate(relocInfo::poll_return_type); -- __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); -+ __ read_polling_page(t0, os::get_polling_page(), relocInfo::poll_return_type); - } - } - -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp -index 8e35530359a..7586af01d99 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp -@@ -48,8 +48,6 @@ class VM_Version : public Abstract_VM_Version { - // Initialization - static void initialize(); - -- constexpr static bool supports_stack_watermark_barrier() { return true; } -- - enum Feature_Flag { - #define CPU_FEATURE_FLAGS(decl) \ - decl(I, "i", 8) \ - -From a032c615883fe2bd557baf40f1439cbae55be206 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Mon, 1 May 2023 15:42:09 +0800 -Subject: [PATCH 005/140] Revert JDK-8221554: aarch64 cross-modifying code - ---- - .../cpu/riscv/macroAssembler_riscv.cpp | 22 ------------------- - .../cpu/riscv/macroAssembler_riscv.hpp | 2 -- - 2 files changed, 24 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 4b6136ae36b..269d76ba69e 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -2716,7 +2716,6 @@ void MacroAssembler::build_frame(int framesize) { - sd(fp, Address(sp, framesize - 2 * wordSize)); - sd(ra, Address(sp, framesize - wordSize)); - if (PreserveFramePointer) { add(fp, sp, framesize); } -- verify_cross_modify_fence_not_required(); - } - - void MacroAssembler::remove_frame(int framesize) { -@@ -3935,26 +3934,5 @@ void MacroAssembler::cmp_l2i(Register dst, Register src1, Register src2, Registe - - void MacroAssembler::safepoint_ifence() { - ifence(); --#ifndef PRODUCT -- if (VerifyCrossModifyFence) { -- // Clear the thread state. -- sb(zr, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); -- } --#endif - } - --#ifndef PRODUCT --void MacroAssembler::verify_cross_modify_fence_not_required() { -- if (VerifyCrossModifyFence) { -- // Check if thread needs a cross modify fence. -- lbu(t0, Address(xthread, in_bytes(JavaThread::requires_cross_modify_fence_offset()))); -- Label fence_not_required; -- beqz(t0, fence_not_required); -- // If it does then fail. -- la(t0, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::verify_cross_modify_fence_failure))); -- mv(c_rarg0, xthread); -- jalr(t0); -- bind(fence_not_required); -- } --} --#endif -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 041c696add6..b59bdadb8bf 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -821,8 +821,6 @@ class MacroAssembler: public Assembler { - void load_reserved(Register addr, enum operand_size size, Assembler::Aqrl acquire); - void store_conditional(Register addr, Register new_val, enum operand_size size, Assembler::Aqrl release); - -- // Check the current thread doesn't need a cross modify fence. -- void verify_cross_modify_fence_not_required() PRODUCT_RETURN; - }; - - #ifdef ASSERT - -From fd89cf689015649a5cb850e1e24dcbb7bb59735a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:11:30 +0800 -Subject: [PATCH 006/140] Revert JDK-8242263: Diagnose synchronization on - primitive wrappers - ---- - src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp | 7 ------- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 7 ------- - src/hotspot/cpu/riscv/riscv.ad | 7 ------- - 3 files changed, 21 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index 6f656c8c533..348546a9ea0 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -64,13 +64,6 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr - - null_check_offset = offset(); - -- if (DiagnoseSyncOnValueBasedClasses != 0) { -- load_klass(hdr, obj); -- lwu(hdr, Address(hdr, Klass::access_flags_offset())); -- andi(t0, hdr, JVM_ACC_IS_VALUE_BASED_CLASS); -- bnez(t0, slow_case, true /* is_far */); -- } -- - // Load object header - ld(hdr, Address(obj, hdr_offset)); - // and mark it as unlocked -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 9090ad0c058..8adc7b1320d 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -782,13 +782,6 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) - // Load object pointer into obj_reg c_rarg3 - ld(obj_reg, Address(lock_reg, obj_offset)); - -- if (DiagnoseSyncOnValueBasedClasses != 0) { -- load_klass(tmp, obj_reg); -- lwu(tmp, Address(tmp, Klass::access_flags_offset())); -- andi(tmp, tmp, JVM_ACC_IS_VALUE_BASED_CLASS); -- bnez(tmp, slow_case); -- } -- - // Load (object->mark() | 1) into swap_reg - ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - ori(swap_reg, t0, 1); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 996fa1fb68f..2eefc71dde0 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1965,13 +1965,6 @@ encode %{ - // Load markWord from object into displaced_header. - __ ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes())); - -- if (DiagnoseSyncOnValueBasedClasses != 0) { -- __ load_klass(flag, oop); -- __ lwu(flag, Address(flag, Klass::access_flags_offset())); -- __ andi(flag, flag, JVM_ACC_IS_VALUE_BASED_CLASS, tmp /* tmp */); -- __ bnez(flag, cont, true /* is_far */); -- } -- - // Check for existing monitor - __ andi(t0, disp_hdr, markWord::monitor_value); - __ bnez(t0, object_has_monitor); - -From feea78c5a227c0a57e57d6d1d544a14682310053 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:24:12 +0800 -Subject: [PATCH 007/140] Revert JDK-8278104: C1 should support the compiler - directive 'BreakAtExecute' - ---- - src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index 348546a9ea0..e5ed25616d6 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -311,7 +311,7 @@ void C1_MacroAssembler::remove_frame(int framesize) { - } - - --void C1_MacroAssembler::verified_entry(bool breakAtEntry) { -+void C1_MacroAssembler::verified_entry() { - // If we have to make this method not-entrant we'll overwrite its - // first instruction with a jump. For this action to be legal we - // must ensure that this first instruction is a J, JAL or NOP. - -From 651009a5783f6f5150b3e75a50069dc841622d33 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 15:57:14 +0800 -Subject: [PATCH 008/140] Revert: JDK-8234562: Move - OrderAccess::release_store*/load_acquire to Atomic JDK-8234736: Harmonize - parameter order in Atomic - store JDK-8234737: Harmonize parameter order in - Atomic - add JDK-8234740: Harmonize parameter order in Atomic - cmpxchg - JDK-8234739: Harmonize parameter order in Atomic - xchg JDK-8236778: Add - Atomic::fetch_and_add - ---- - .../os_cpu/linux_riscv/atomic_linux_riscv.hpp | 51 +++++++------------ - .../linux_riscv/orderAccess_linux_riscv.hpp | 31 +++++++---- - 2 files changed, 39 insertions(+), 43 deletions(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp -index 761da5d743e..9b8b1a31774 100644 ---- a/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp -+++ b/src/hotspot/os_cpu/linux_riscv/atomic_linux_riscv.hpp -@@ -33,25 +33,31 @@ - // Note that memory_order_conservative requires a full barrier after atomic stores. - // See https://patchwork.kernel.org/patch/3575821/ - -+#define FULL_MEM_BARRIER __sync_synchronize() -+#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE); -+#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE); -+ - template --struct Atomic::PlatformAdd { -- template -- D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { -+struct Atomic::PlatformAdd -+ : Atomic::FetchAndAdd > -+{ -+ template -+ D add_and_fetch(I add_value, D volatile* dest, atomic_memory_order order) const { - D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); - FULL_MEM_BARRIER; - return res; - } - -- template -- D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { -- return add_and_fetch(dest, add_value, order) - add_value; -+ template -+ D fetch_and_add(I add_value, D volatile* dest, atomic_memory_order order) const { -+ return add_and_fetch(add_value, dest, order) - add_value; - } - }; - - template - template --inline T Atomic::PlatformXchg::operator()(T volatile* dest, -- T exchange_value, -+inline T Atomic::PlatformXchg::operator()(T exchange_value, -+ T volatile* dest, - atomic_memory_order order) const { - STATIC_ASSERT(byte_size == sizeof(T)); - T res = __atomic_exchange_n(dest, exchange_value, __ATOMIC_RELEASE); -@@ -62,9 +68,9 @@ inline T Atomic::PlatformXchg::operator()(T volatile* dest, - // __attribute__((unused)) on dest is to get rid of spurious GCC warnings. - template - template --inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attribute__((unused)), -+inline T Atomic::PlatformCmpxchg::operator()(T exchange_value, -+ T volatile* dest __attribute__((unused)), - T compare_value, -- T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(byte_size == sizeof(T)); - T value = compare_value; -@@ -83,9 +89,9 @@ inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attri - - template<> - template --inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__((unused)), -+inline T Atomic::PlatformCmpxchg<4>::operator()(T exchange_value, -+ T volatile* dest __attribute__((unused)), - T compare_value, -- T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(4 == sizeof(T)); - if (order != memory_order_relaxed) { -@@ -110,25 +116,4 @@ inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest __attribute__(( - return rv; - } - --template --struct Atomic::PlatformOrderedLoad --{ -- template -- T operator()(const volatile T* p) const { T data; __atomic_load(const_cast(p), &data, __ATOMIC_ACQUIRE); return data; } --}; -- --template --struct Atomic::PlatformOrderedStore --{ -- template -- void operator()(volatile T* p, T v) const { __atomic_store(const_cast(p), &v, __ATOMIC_RELEASE); } --}; -- --template --struct Atomic::PlatformOrderedStore --{ -- template -- void operator()(volatile T* p, T v) const { release_store(p, v); OrderAccess::fence(); } --}; -- - #endif // OS_CPU_LINUX_RISCV_ATOMIC_LINUX_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp -index 1c33dc1e87f..5b5d35553f7 100644 ---- a/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp -+++ b/src/hotspot/os_cpu/linux_riscv/orderAccess_linux_riscv.hpp -@@ -37,10 +37,6 @@ inline void OrderAccess::storestore() { release(); } - inline void OrderAccess::loadstore() { acquire(); } - inline void OrderAccess::storeload() { fence(); } - --#define FULL_MEM_BARRIER __sync_synchronize() --#define READ_MEM_BARRIER __atomic_thread_fence(__ATOMIC_ACQUIRE); --#define WRITE_MEM_BARRIER __atomic_thread_fence(__ATOMIC_RELEASE); -- - inline void OrderAccess::acquire() { - READ_MEM_BARRIER; - } -@@ -53,11 +49,26 @@ inline void OrderAccess::fence() { - FULL_MEM_BARRIER; - } - --inline void OrderAccess::cross_modify_fence_impl() { -- asm volatile("fence.i" : : : "memory"); -- if (UseConservativeFence) { -- asm volatile("fence ir, ir" : : : "memory"); -- } --} -+ -+template -+struct OrderAccess::PlatformOrderedLoad -+{ -+ template -+ T operator()(const volatile T* p) const { T data; __atomic_load(const_cast(p), &data, __ATOMIC_ACQUIRE); return data; } -+}; -+ -+template -+struct OrderAccess::PlatformOrderedStore -+{ -+ template -+ void operator()(T v, volatile T* p) const { __atomic_store(const_cast(p), &v, __ATOMIC_RELEASE); } -+}; -+ -+template -+struct OrderAccess::PlatformOrderedStore -+{ -+ template -+ void operator()(T v, volatile T* p) const { release_store(p, v); OrderAccess::fence(); } -+}; - - #endif // OS_CPU_LINUX_RISCV_ORDERACCESS_LINUX_RISCV_HPP - -From b078a2ec01598fbcd99aea61af15d44f9c884aaa Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 21:07:42 +0800 -Subject: [PATCH 009/140] Revert JDK-8229258: Rework markOop and markOopDesc - into a simpler mark word value carrier - ---- - .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 4 ++-- - .../shenandoahBarrierSetAssembler_riscv.cpp | 4 ++-- - src/hotspot/cpu/riscv/riscv.ad | 22 +++++++++---------- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 2 +- - 4 files changed, 16 insertions(+), 16 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index e5ed25616d6..2d52343587e 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -67,7 +67,7 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr - // Load object header - ld(hdr, Address(obj, hdr_offset)); - // and mark it as unlocked -- ori(hdr, hdr, markWord::unlocked_value); -+ ori(hdr, hdr, markOopDesc::unlocked_value); - // save unlocked object header into the displaced header location on the stack - sd(hdr, Address(disp_hdr, 0)); - // test if object header is still the same (i.e. unlocked), and if so, store the -@@ -141,7 +141,7 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i - void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register tmp1, Register tmp2) { - assert_different_registers(obj, klass, len); - // This assumes that all prototype bits fitr in an int32_t -- mv(tmp1, (int32_t)(intptr_t)markWord::prototype().value()); -+ mv(tmp1, (int32_t)(intptr_t)markOopDesc::prototype()); - sd(tmp1, Address(obj, oopDesc::mark_offset_in_bytes())); - - if (UseCompressedClassPointers) { // Take care not to kill klass -diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -index d0ac6e52436..84e1205bc25 100644 ---- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -@@ -216,9 +216,9 @@ void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssemb - Label done; - __ ld(tmp, Address(dst, oopDesc::mark_offset_in_bytes())); - __ xori(tmp, tmp, -1); // eon with 0 is equivalent to XOR with -1 -- __ andi(t2, tmp, markWord::lock_mask_in_place); -+ __ andi(t2, tmp, markOopDesc::lock_mask_in_place); - __ bnez(t2, done); -- __ ori(tmp, tmp, markWord::marked_value); -+ __ ori(tmp, tmp, markOopDesc::marked_value); - __ xori(dst, tmp, -1); // eon with 0 is equivalent to XOR with -1 - __ bind(done); - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 2eefc71dde0..44ab44dece1 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1966,12 +1966,12 @@ encode %{ - __ ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes())); - - // Check for existing monitor -- __ andi(t0, disp_hdr, markWord::monitor_value); -+ __ andi(t0, disp_hdr, markOopDesc::monitor_value); - __ bnez(t0, object_has_monitor); - - if (!UseHeavyMonitors) { - // Set tmp to be (markWord of object | UNLOCK_VALUE). -- __ ori(tmp, disp_hdr, markWord::unlocked_value); -+ __ ori(tmp, disp_hdr, markOopDesc::unlocked_value); - - // Initialize the box. (Must happen before we update the object mark!) - __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -@@ -1993,7 +1993,7 @@ encode %{ - // Check if the owner is self by comparing the value in the - // markWord of object (disp_hdr) with the stack pointer. - __ sub(disp_hdr, disp_hdr, sp); -- __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markWord::lock_mask_in_place)); -+ __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markOopDesc::lock_mask_in_place)); - // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, - // hence we can store 0 as the displaced header in the box, which indicates that it is a - // recursive lock. -@@ -2012,15 +2012,15 @@ encode %{ - // otherwise m->owner may contain a thread or a stack address. - // - // Try to CAS m->owner from NULL to current thread. -- __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markWord::monitor_value)); -+ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value)); - __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, - Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) - - // Store a non-null value into the box to avoid looking like a re-entrant - // lock. The fast-path monitor unlock code checks for -- // markWord::monitor_value so use markWord::unused_mark which has the -+ // markOopDesc::monitor_value so use markOopDesc::unused_mark which has the - // relevant bit set, and also matches ObjectSynchronizer::slow_enter. -- __ mv(tmp, (address)markWord::unused_mark().value()); -+ __ mv(tmp, (address)markOopDesc::unused_mark()); - __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); - - __ beqz(flag, cont); // CAS success means locking succeeded -@@ -2029,9 +2029,9 @@ encode %{ - - // Recursive lock case - __ mv(flag, zr); -- __ ld(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); -+ __ ld(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markOopDesc::monitor_value)); - __ add(tmp, tmp, 1u); -- __ sd(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markWord::monitor_value)); -+ __ sd(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markOopDesc::monitor_value)); - - __ bind(cont); - %} -@@ -2060,7 +2060,7 @@ encode %{ - - // Handle existing monitor. - __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); -- __ andi(t0, disp_hdr, markWord::monitor_value); -+ __ andi(t0, disp_hdr, markOopDesc::monitor_value); - __ bnez(t0, object_has_monitor); - - if (!UseHeavyMonitors) { -@@ -2080,8 +2080,8 @@ encode %{ - - // Handle existing monitor. - __ bind(object_has_monitor); -- STATIC_ASSERT(markWord::monitor_value <= INT_MAX); -- __ add(tmp, tmp, -(int)markWord::monitor_value); // monitor -+ STATIC_ASSERT(markOopDesc::monitor_value <= INT_MAX); -+ __ add(tmp, tmp, -(int)markOopDesc::monitor_value); // monitor - __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); - - Label notRecursive; -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index d2a301c6e74..4e388ac4eaa 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -3559,7 +3559,7 @@ void TemplateTable::_new() { - - // initialize object hader only. - __ bind(initialize_header); -- __ mv(t0, (intptr_t)markWord::prototype().value()); -+ __ mv(t0, (intptr_t)markOopDesc::prototype()); - __ sd(t0, Address(x10, oopDesc::mark_offset_in_bytes())); - __ store_klass_gap(x10, zr); // zero klass gap for compressed oops - __ store_klass(x10, x14); // store klass last - -From 4b27cd8d4cfa8fb5f0f78aecaebb17d19362f300 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Fri, 31 Mar 2023 16:24:36 +0800 -Subject: [PATCH 010/140] Revert: JDK-8239895: assert(_stack_base != 0LL) - failed: Sanity check JDK-8238988: Rename thread "in stack" methods and add - in_stack_range JDK-8234372: Investigate use of Thread::stack_base() and - queries for "in stack" JDK-8203481: Incorrect constraint for unextended_sp in - frame:safe_for_sender - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 32 +++++++++++++++++++-------- - 1 file changed, 23 insertions(+), 9 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 41e52a4d491..8e7babe2c61 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -56,13 +56,21 @@ void RegisterMap::check_location_valid() { - // Profiling/safepoint support - - bool frame::safe_for_sender(JavaThread *thread) { -- address addr_sp = (address)_sp; -- address addr_fp = (address)_fp; -+ address sp = (address)_sp; -+ address fp = (address)_fp; - address unextended_sp = (address)_unextended_sp; - - // consider stack guards when trying to determine "safe" stack pointers -+ static size_t stack_guard_size = os::uses_stack_guard_pages() ? -+ (JavaThread::stack_red_zone_size() + JavaThread::stack_yellow_zone_size()) : 0; -+ size_t usable_stack_size = thread->stack_size() - stack_guard_size; -+ - // sp must be within the usable part of the stack (not in guards) -- if (!thread->is_in_usable_stack(addr_sp)) { -+ bool sp_safe = (sp < thread->stack_base()) && -+ (sp >= thread->stack_base() - usable_stack_size); -+ -+ -+ if (!sp_safe) { - return false; - } - -@@ -79,14 +87,15 @@ bool frame::safe_for_sender(JavaThread *thread) { - // So unextended sp must be within the stack but we need not to check - // that unextended sp >= sp - -- if (!thread->is_in_full_stack_checked(unextended_sp)) { -+ bool unextended_sp_safe = (unextended_sp < thread->stack_base()); -+ -+ if (!unextended_sp_safe) { - return false; - } - - // an fp must be within the stack and above (but not equal) sp - // second evaluation on fp+ is added to handle situation where fp is -1 -- bool fp_safe = thread->is_in_stack_range_excl(addr_fp, addr_sp) && -- thread->is_in_full_stack_checked(addr_fp + (return_addr_offset * sizeof(void*))); -+ bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); - - // We know sp/unextended_sp are safe only fp is questionable here - -@@ -147,7 +156,7 @@ bool frame::safe_for_sender(JavaThread *thread) { - - sender_sp = _unextended_sp + _cb->frame_size(); - // Is sender_sp safe? -- if (!thread->is_in_full_stack_checked((address)sender_sp)) { -+ if ((address)sender_sp >= thread->stack_base()) { - return false; - } - -@@ -163,7 +172,10 @@ bool frame::safe_for_sender(JavaThread *thread) { - // fp is always saved in a recognizable place in any code we generate. However - // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved fp - // is really a frame pointer. -- if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { -+ -+ bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); -+ -+ if (!saved_fp_safe) { - return false; - } - -@@ -196,7 +208,9 @@ bool frame::safe_for_sender(JavaThread *thread) { - - // Could be the call_stub - if (StubRoutines::returns_to_call_stub(sender_pc)) { -- if (!thread->is_in_stack_range_excl((address)saved_fp, (address)sender_sp)) { -+ bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); -+ -+ if (!saved_fp_safe) { - return false; - } - - -From d1b463b6c00c75664a49719f75bef8e6408f12df Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Fri, 31 Mar 2023 17:10:33 +0800 -Subject: [PATCH 011/140] Revert JDK-8173585: Intrinsify - StringLatin1.indexOf(char) - ---- - src/hotspot/cpu/riscv/riscv.ad | 19 ------------------- - 1 file changed, 19 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 44ab44dece1..8c7a8ede815 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -9826,7 +9826,6 @@ instruct stringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, - iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) - %{ - match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::U); - effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, - TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); - -@@ -9840,24 +9839,6 @@ instruct stringU_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, - %} - - --instruct stringL_indexof_char(iRegP_R11 str1, iRegI_R12 cnt1, iRegI_R13 ch, -- iRegI_R10 result, iRegINoSp tmp1, iRegINoSp tmp2, -- iRegINoSp tmp3, iRegINoSp tmp4, rFlagsReg cr) --%{ -- match(Set result (StrIndexOfChar (Binary str1 cnt1) ch)); -- predicate(((StrIndexOfCharNode*)n)->encoding() == StrIntrinsicNode::L); -- effect(USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP_DEF result, -- TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr); -- -- format %{ "StringUTF16 IndexOf char[] $str1,$cnt1,$ch -> $result" %} -- ins_encode %{ -- __ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, -- $result$$Register, $tmp1$$Register, $tmp2$$Register, -- $tmp3$$Register, $tmp4$$Register, true /* isL */); -- %} -- ins_pipe(pipe_class_memory); --%} -- - // clearing of an array - instruct clearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy) - %{ - -From a0cdf8dfb05dbff34d2ca23104d08ae21b2d7f70 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 12:25:36 +0800 -Subject: [PATCH 012/140] Revert JDK-8281632: riscv: Improve interpreter stack - banging, and change the register t1->t0 - ---- - .../templateInterpreterGenerator_riscv.cpp | 42 ++++--------------- - 1 file changed, 8 insertions(+), 34 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index 6537b2dbd94..76ae6f89e27 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -895,42 +895,16 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract - } - - void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { -- // See more discussion in stackOverflow.hpp. -- -- const int shadow_zone_size = checked_cast(StackOverflow::stack_shadow_zone_size()); -+ // Bang each page in the shadow zone. We can't assume it's been done for -+ // an interpreter frame with greater than a page of locals, so each page -+ // needs to be checked. Only true for non-native. -+ const int n_shadow_pages = JavaThread::stack_shadow_zone_size() / os::vm_page_size(); -+ const int start_page = native_call ? n_shadow_pages : 1; - const int page_size = os::vm_page_size(); -- const int n_shadow_pages = shadow_zone_size / page_size; -- --#ifdef ASSERT -- Label L_good_limit; -- __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); -- __ bnez(t0, L_good_limit); -- __ stop("shadow zone safe limit is not initialized"); -- __ bind(L_good_limit); -- -- Label L_good_watermark; -- __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -- __ bnez(t0, L_good_watermark); -- __ stop("shadow zone growth watermark is not initialized"); -- __ bind(L_good_watermark); --#endif -- -- Label L_done; -- -- __ ld(t0, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -- __ bgtu(sp, t0, L_done); -- -- for (int p = 1; p <= n_shadow_pages; p++) { -- __ bang_stack_with_offset(p * page_size); -+ for (int pages = start_page; pages <= n_shadow_pages ; pages++) { -+ __ sub(t0, sp, pages * page_size); -+ __ sd(zr, Address(t0)); - } -- -- // Record the new watermark, but only if the update is above the safe limit. -- // Otherwise, the next time around the check above would pass the safe limit. -- __ ld(t0, Address(xthread, JavaThread::shadow_zone_safe_limit())); -- __ bleu(sp, t0, L_done); -- __ sd(sp, Address(xthread, JavaThread::shadow_zone_growth_watermark())); -- -- __ bind(L_done); - } - - // Interpreter stub for calling a native method. (asm interpreter) - -From 8db4bf1400d92c80a0adef8a5ec12adbf595c03f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 14:56:25 +0800 -Subject: [PATCH 013/140] Port aarch64 style sig handler from - os_linux_aarch64.cpp - ---- - .../os_cpu/linux_riscv/os_linux_riscv.cpp | 224 +++++++++++++----- - 1 file changed, 168 insertions(+), 56 deletions(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -index 1f46bbab0a2..db15f1946e2 100644 ---- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -@@ -48,7 +48,6 @@ - #include "runtime/stubRoutines.hpp" - #include "runtime/thread.inline.hpp" - #include "runtime/timer.hpp" --#include "signals_posix.hpp" - #include "utilities/debug.hpp" - #include "utilities/events.hpp" - #include "utilities/vmError.hpp" -@@ -172,31 +171,138 @@ NOINLINE frame os::current_frame() { - } - - // Utility functions --bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, -- ucontext_t* uc, JavaThread* thread) { -+extern "C" JNIEXPORT int -+JVM_handle_linux_signal(int sig, -+ siginfo_t* info, -+ void* ucVoid, -+ int abort_if_unrecognized) { -+ ucontext_t* uc = (ucontext_t*) ucVoid; -+ -+ Thread* t = Thread::current_or_null_safe(); -+ -+ // Must do this before SignalHandlerMark, if crash protection installed we will longjmp away -+ // (no destructors can be run) -+ os::ThreadCrashProtection::check_crash_protection(sig, t); -+ -+ SignalHandlerMark shm(t); -+ -+ // Note: it's not uncommon that JNI code uses signal/sigset to install -+ // then restore certain signal handler (e.g. to temporarily block SIGPIPE, -+ // or have a SIGILL handler when detecting CPU type). When that happens, -+ // JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To -+ // avoid unnecessary crash when libjsig is not preloaded, try handle signals -+ // that do not require siginfo/ucontext first. -+ -+ if (sig == SIGPIPE || sig == SIGXFSZ) { -+ // allow chained handler to go first -+ if (os::Linux::chained_handler(sig, info, ucVoid)) { -+ return true; -+ } else { -+ // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 -+ return true; -+ } -+ } -+ -+#ifdef CAN_SHOW_REGISTERS_ON_ASSERT -+ if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) { -+ if (handle_assert_poison_fault(ucVoid, info->si_addr)) { -+ return 1; -+ } -+ } -+#endif -+ -+ JavaThread* thread = NULL; -+ VMThread* vmthread = NULL; -+ if (os::Linux::signal_handlers_are_installed) { -+ if (t != NULL ){ -+ if(t->is_Java_thread()) { -+ thread = (JavaThread *) t; -+ } -+ else if(t->is_VM_thread()){ -+ vmthread = (VMThread *)t; -+ } -+ } -+ } -+ -+ // Handle SafeFetch faults -+ if ((sig == SIGSEGV || sig == SIGBUS) && uc != NULL) { -+ address const pc = (address) os::Linux::ucontext_get_pc(uc); -+ if (pc && StubRoutines::is_safefetch_fault(pc)) { -+ os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc)); -+ return 1; -+ } -+ } - - // decide if this trap can be handled by a stub - address stub = NULL; - -- address pc = NULL; -+ address pc = NULL; - - //%note os_trap_1 - if (info != NULL && uc != NULL && thread != NULL) { -- pc = (address) os::Posix::ucontext_get_pc(uc); -- -- address addr = (address) info->si_addr; -- -- // Make sure the high order byte is sign extended, as it may be masked away by the hardware. -- if ((uintptr_t(addr) & (uintptr_t(1) << 55)) != 0) { -- addr = address(uintptr_t(addr) | (uintptr_t(0xFF) << 56)); -- } -+ pc = (address) os::Linux::ucontext_get_pc(uc); - - // Handle ALL stack overflow variations here - if (sig == SIGSEGV) { -+ address addr = (address) info->si_addr; -+ - // check if fault address is within thread stack -- if (thread->is_in_full_stack(addr)) { -- if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) { -- return true; // continue -+ if (thread->on_local_stack(addr)) { -+ // stack overflow -+ if (thread->in_stack_yellow_reserved_zone(addr)) { -+ if (thread->thread_state() == _thread_in_Java) { -+ if (thread->in_stack_reserved_zone(addr)) { -+ frame fr; -+ if (os::Linux::get_frame_at_stack_banging_point(thread, uc, &fr)) { -+ assert(fr.is_java_frame(), "Must be a Java frame"); -+ frame activation = -+ SharedRuntime::look_for_reserved_stack_annotated_method(thread, fr); -+ if (activation.sp() != NULL) { -+ thread->disable_stack_reserved_zone(); -+ if (activation.is_interpreted_frame()) { -+ thread->set_reserved_stack_activation((address)( -+ activation.fp() + frame::interpreter_frame_initial_sp_offset)); -+ } else { -+ thread->set_reserved_stack_activation((address)activation.unextended_sp()); -+ } -+ return 1; -+ } -+ } -+ } -+ // Throw a stack overflow exception. Guard pages will be reenabled -+ // while unwinding the stack. -+ thread->disable_stack_yellow_reserved_zone(); -+ stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); -+ } else { -+ // Thread was in the vm or native code. Return and try to finish. -+ thread->disable_stack_yellow_reserved_zone(); -+ return 1; -+ } -+ } else if (thread->in_stack_red_zone(addr)) { -+ // Fatal red zone violation. Disable the guard pages and fall through -+ // to handle_unexpected_exception way down below. -+ thread->disable_stack_red_zone(); -+ tty->print_raw_cr("An irrecoverable stack overflow has occurred."); -+ -+ // This is a likely cause, but hard to verify. Let's just print -+ // it as a hint. -+ tty->print_raw_cr("Please check if any of your loaded .so files has " -+ "enabled executable stack (see man page execstack(8))"); -+ } else { -+ // Accessing stack address below sp may cause SEGV if current -+ // thread has MAP_GROWSDOWN stack. This should only happen when -+ // current thread was created by user code with MAP_GROWSDOWN flag -+ // and then attached to VM. See notes in os_linux.cpp. -+ if (thread->osthread()->expanding_stack() == 0) { -+ thread->osthread()->set_expanding_stack(); -+ if (os::Linux::manually_expand_stack(thread, addr)) { -+ thread->osthread()->clear_expanding_stack(); -+ return 1; -+ } -+ thread->osthread()->clear_expanding_stack(); -+ } else { -+ fatal("recursive segv. expanding stack."); -+ } - } - } - } -@@ -212,7 +318,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, - tty->print_cr("trap: zombie_not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); -- } else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { -+ } else if (sig == SIGSEGV && os::is_poll_address((address)info->si_addr)) { - stub = SharedRuntime::get_poll_stub(pc); - } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { - // BugId 4454115: A read from a MappedByteBuffer can fault -@@ -220,34 +326,12 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, - // Do not crash the VM in such a case. - CodeBlob* cb = CodeCache::find_blob_unsafe(pc); - CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL; -- bool is_unsafe_arraycopy = (thread->doing_unsafe_access() && UnsafeCopyMemory::contains_pc(pc)); -- if ((nm != NULL && nm->has_unsafe_access()) || is_unsafe_arraycopy) { -+ if (nm != NULL && nm->has_unsafe_access()) { - address next_pc = pc + NativeCall::instruction_size; -- if (is_unsafe_arraycopy) { -- next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); -- } - stub = SharedRuntime::handle_unsafe_access(thread, next_pc); - } -- } else if (sig == SIGILL && nativeInstruction_at(pc)->is_stop()) { -- // Pull a pointer to the error message out of the instruction -- // stream. -- const uint64_t *detail_msg_ptr -- = (uint64_t*)(pc + NativeInstruction::instruction_size); -- const char *detail_msg = (const char *)*detail_msg_ptr; -- const char *msg = "stop"; -- if (TraceTraps) { -- tty->print_cr("trap: %s: (SIGILL)", msg); -- } -- -- // End life with a fatal error, message and detail message and the context. -- // Note: no need to do any post-processing here (e.g. signal chaining) -- va_list va_dummy; -- VMError::report_and_die(thread, uc, NULL, 0, msg, detail_msg, va_dummy); -- va_end(va_dummy); -- -- ShouldNotReachHere(); - } else if (sig == SIGFPE && -- (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { -+ (info->si_code == FPE_INTDIV || info->si_code == FPE_FLTDIV)) { - stub = - SharedRuntime:: - continuation_for_implicit_exception(thread, -@@ -255,42 +339,70 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, - SharedRuntime:: - IMPLICIT_DIVIDE_BY_ZERO); - } else if (sig == SIGSEGV && -- MacroAssembler::uses_implicit_null_check((void*)addr)) { -+ !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { - // Determination of interpreter/vtable stub/compiled code null exception - stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - } -- } else if ((thread->thread_state() == _thread_in_vm || -- thread->thread_state() == _thread_in_native) && -- sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ -- thread->doing_unsafe_access()) { -+ } else if (thread->thread_state() == _thread_in_vm && -+ sig == SIGBUS && /* info->si_code == BUS_OBJERR && */ -+ thread->doing_unsafe_access()) { - address next_pc = pc + NativeCall::instruction_size; -- if (UnsafeCopyMemory::contains_pc(pc)) { -- next_pc = UnsafeCopyMemory::page_error_continue_pc(pc); -- } - stub = SharedRuntime::handle_unsafe_access(thread, next_pc); - } - - // jni_fast_GetField can trap at certain pc's if a GC kicks in - // and the heap gets shrunk before the field access. - if ((sig == SIGSEGV) || (sig == SIGBUS)) { -- address addr_slow = JNI_FastGetField::find_slowcase_pc(pc); -- if (addr_slow != (address)-1) { -- stub = addr_slow; -+ address addr = JNI_FastGetField::find_slowcase_pc(pc); -+ if (addr != (address)-1) { -+ stub = addr; - } - } -+ -+ // Check to see if we caught the safepoint code in the -+ // process of write protecting the memory serialization page. -+ // It write enables the page immediately after protecting it -+ // so we can just return to retry the write. -+ if ((sig == SIGSEGV) && -+ os::is_memory_serialize_page(thread, (address) info->si_addr)) { -+ // Block current thread until the memory serialize page permission restored. -+ os::block_on_serialize_page_trap(); -+ return true; -+ } - } - - if (stub != NULL) { - // save all thread context in case we need to restore it -- if (thread != NULL) { -- thread->set_saved_exception_pc(pc); -- } -+ if (thread != NULL) thread->set_saved_exception_pc(pc); - -- os::Posix::ucontext_set_pc(uc, stub); -+ os::Linux::ucontext_set_pc(uc, stub); - return true; - } - -- return false; // Mute compiler -+ // signal-chaining -+ if (os::Linux::chained_handler(sig, info, ucVoid)) { -+ return true; -+ } -+ -+ if (!abort_if_unrecognized) { -+ // caller wants another chance, so give it to him -+ return false; -+ } -+ -+ if (pc == NULL && uc != NULL) { -+ pc = os::Linux::ucontext_get_pc(uc); -+ } -+ -+ // unmask current signal -+ sigset_t newset; -+ sigemptyset(&newset); -+ sigaddset(&newset, sig); -+ sigprocmask(SIG_UNBLOCK, &newset, NULL); -+ -+ VMError::report_and_die(t, sig, pc, info, ucVoid); -+ -+ ShouldNotReachHere(); -+ return true; // Mute compiler - } - - void os::Linux::init_thread_fpu_state(void) { - -From fd3897410308e2fc54d84a9bd453b1b375e6aace Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 15:24:57 +0800 -Subject: [PATCH 014/140] Revert: JDK-8248240: Remove extendedPC.hpp and - fetch_frame_from_ucontext JDK-8253742: POSIX signal code cleanup - ---- - .../os_cpu/linux_riscv/os_linux_riscv.cpp | 38 ++++++++++++++----- - .../os_cpu/linux_riscv/thread_linux_riscv.cpp | 9 +++-- - 2 files changed, 33 insertions(+), 14 deletions(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -index db15f1946e2..4f1c84c60a0 100644 ---- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -@@ -37,6 +37,7 @@ - #include "prims/jniFastGetField.hpp" - #include "prims/jvm_misc.hpp" - #include "runtime/arguments.hpp" -+#include "runtime/extendedPC.hpp" - #include "runtime/frame.inline.hpp" - #include "runtime/interfaceSupport.inline.hpp" - #include "runtime/java.hpp" -@@ -85,11 +86,11 @@ char* os::non_memory_address_word() { - return (char*) -1; - } - --address os::Posix::ucontext_get_pc(const ucontext_t * uc) { -+address os::Linux::ucontext_get_pc(const ucontext_t * uc) { - return (address)uc->uc_mcontext.__gregs[REG_PC]; - } - --void os::Posix::ucontext_set_pc(ucontext_t * uc, address pc) { -+void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { - uc->uc_mcontext.__gregs[REG_PC] = (intptr_t)pc; - } - -@@ -101,13 +102,29 @@ intptr_t* os::Linux::ucontext_get_fp(const ucontext_t * uc) { - return (intptr_t*)uc->uc_mcontext.__gregs[REG_FP]; - } - --address os::fetch_frame_from_context(const void* ucVoid, -- intptr_t** ret_sp, intptr_t** ret_fp) { -- address epc; -+// For Forte Analyzer AsyncGetCallTrace profiling support - thread -+// is currently interrupted by SIGPROF. -+// os::Solaris::fetch_frame_from_ucontext() tries to skip nested signal -+// frames. Currently we don't do that on Linux, so it's the same as -+// os::fetch_frame_from_context(). -+ExtendedPC os::Linux::fetch_frame_from_ucontext(Thread* thread, -+ const ucontext_t* uc, intptr_t** ret_sp, intptr_t** ret_fp) { -+ -+ assert(thread != NULL, "just checking"); -+ assert(ret_sp != NULL, "just checking"); -+ assert(ret_fp != NULL, "just checking"); -+ -+ return os::fetch_frame_from_context(uc, ret_sp, ret_fp); -+} -+ -+ExtendedPC os::fetch_frame_from_context(const void* ucVoid, -+ intptr_t** ret_sp, intptr_t** ret_fp) { -+ -+ ExtendedPC epc; - const ucontext_t* uc = (const ucontext_t*)ucVoid; - - if (uc != NULL) { -- epc = os::Posix::ucontext_get_pc(uc); -+ epc = ExtendedPC(os::Linux::ucontext_get_pc(uc)); - if (ret_sp != NULL) { - *ret_sp = os::Linux::ucontext_get_sp(uc); - } -@@ -115,7 +132,8 @@ address os::fetch_frame_from_context(const void* ucVoid, - *ret_fp = os::Linux::ucontext_get_fp(uc); - } - } else { -- epc = NULL; -+ // construct empty ExtendedPC for return value checking -+ epc = ExtendedPC(NULL); - if (ret_sp != NULL) { - *ret_sp = (intptr_t *)NULL; - } -@@ -142,8 +160,8 @@ frame os::fetch_compiled_frame_from_context(const void* ucVoid) { - frame os::fetch_frame_from_context(const void* ucVoid) { - intptr_t* frame_sp = NULL; - intptr_t* frame_fp = NULL; -- address epc = fetch_frame_from_context(ucVoid, &frame_sp, &frame_fp); -- return frame(frame_sp, frame_fp, epc); -+ ExtendedPC epc = fetch_frame_from_context(ucVoid, &frame_sp, &frame_fp); -+ return frame(frame_sp, frame_fp, epc.pc()); - } - - // By default, gcc always saves frame pointer rfp on this stack. This -@@ -465,7 +483,7 @@ void os::print_context(outputStream *st, const void *context) { - // Note: it may be unsafe to inspect memory near pc. For example, pc may - // point to garbage if entry point in an nmethod is corrupted. Leave - // this at the end, and hope for the best. -- address pc = os::Posix::ucontext_get_pc(uc); -+ address pc = os::Linux::ucontext_get_pc(uc); - print_instructions(st, pc, sizeof(char)); - st->cr(); - } -diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -index 3100572e9fd..e46efc420b0 100644 ---- a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -@@ -61,16 +61,17 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) - - intptr_t* ret_fp = NULL; - intptr_t* ret_sp = NULL; -- address addr = os::fetch_frame_from_context(uc, &ret_sp, &ret_fp); -- if (addr == NULL || ret_sp == NULL ) { -+ ExtendedPC addr = os::Linux::fetch_frame_from_ucontext(this, uc, -+ &ret_sp, &ret_fp); -+ if (addr.pc() == NULL || ret_sp == NULL ) { - // ucontext wasn't useful - return false; - } - -- frame ret_frame(ret_sp, ret_fp, addr); -+ frame ret_frame(ret_sp, ret_fp, addr.pc()); - if (!ret_frame.safe_for_sender(this)) { - #ifdef COMPILER2 -- frame ret_frame2(ret_sp, NULL, addr); -+ frame ret_frame2(ret_sp, NULL, addr.pc()); - if (!ret_frame2.safe_for_sender(this)) { - // nothing else to try if the frame isn't good - return false; - -From 892b40a435ae3f7e85659100ef68db1aeda7ef23 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 15:33:50 +0800 -Subject: [PATCH 015/140] Revert JDK-8263002: Remove CDS MiscCode region - ---- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 10 ++++++++++ - src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp | 6 ++++++ - 2 files changed, 16 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 4daed17df10..21aa3b58c09 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -187,6 +187,16 @@ bool SharedRuntime::is_wide_vector(int size) { - return false; - } - -+size_t SharedRuntime::trampoline_size() { -+ return 6 * NativeInstruction::instruction_size; -+} -+ -+void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destination) { -+ int32_t offset = 0; -+ __ movptr_with_offset(t0, destination, offset); -+ __ jalr(x0, t0, offset); -+} -+ - // The java_calling_convention describes stack locations as ideal slots on - // a frame with no abi restrictions. Since we must observe abi restrictions - // (like the placement of the register window) the slots must be biased by -diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -index e46efc420b0..31d9254d8ad 100644 ---- a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -@@ -68,6 +68,12 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) - return false; - } - -+ if (MetaspaceShared::is_in_trampoline_frame(addr.pc())) { -+ // In the middle of a trampoline call. Bail out for safety. -+ // This happens rarely so shouldn't affect profiling. -+ return false; -+ } -+ - frame ret_frame(ret_sp, ret_fp, addr.pc()); - if (!ret_frame.safe_for_sender(this)) { - #ifdef COMPILER2 - -From 945a317797bc96efe3f0717ca7258f081b96b14d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 15:52:43 +0800 -Subject: [PATCH 016/140] Revert JDK-8254158: Consolidate per-platform stack - overflow handling code - ---- - .../os_cpu/linux_riscv/os_linux_riscv.cpp | 52 ++++++++++++++----- - 1 file changed, 40 insertions(+), 12 deletions(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -index 4f1c84c60a0..8b772892b4b 100644 ---- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp -@@ -145,18 +145,6 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, - return epc; - } - --frame os::fetch_compiled_frame_from_context(const void* ucVoid) { -- const ucontext_t* uc = (const ucontext_t*)ucVoid; -- // In compiled code, the stack banging is performed before RA -- // has been saved in the frame. RA is live, and SP and FP -- // belong to the caller. -- intptr_t* frame_fp = os::Linux::ucontext_get_fp(uc); -- intptr_t* frame_sp = os::Linux::ucontext_get_sp(uc); -- address frame_pc = (address)(uc->uc_mcontext.__gregs[REG_LR] -- - NativeInstruction::instruction_size); -- return frame(frame_sp, frame_fp, frame_pc); --} -- - frame os::fetch_frame_from_context(const void* ucVoid) { - intptr_t* frame_sp = NULL; - intptr_t* frame_fp = NULL; -@@ -164,6 +152,46 @@ frame os::fetch_frame_from_context(const void* ucVoid) { - return frame(frame_sp, frame_fp, epc.pc()); - } - -+bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* uc, frame* fr) { -+ address pc = (address) os::Linux::ucontext_get_pc(uc); -+ if (Interpreter::contains(pc)) { -+ // interpreter performs stack banging after the fixed frame header has -+ // been generated while the compilers perform it before. To maintain -+ // semantic consistency between interpreted and compiled frames, the -+ // method returns the Java sender of the current frame. -+ *fr = os::fetch_frame_from_context(uc); -+ if (!fr->is_first_java_frame()) { -+ assert(fr->safe_for_sender(thread), "Safety check"); -+ *fr = fr->java_sender(); -+ } -+ } else { -+ // more complex code with compiled code -+ assert(!Interpreter::contains(pc), "Interpreted methods should have been handled above"); -+ CodeBlob* cb = CodeCache::find_blob(pc); -+ if (cb == NULL || !cb->is_nmethod() || cb->is_frame_complete_at(pc)) { -+ // Not sure where the pc points to, fallback to default -+ // stack overflow handling -+ return false; -+ } else { -+ // In compiled code, the stack banging is performed before RA -+ // has been saved in the frame. RA is live, and SP and FP -+ // belong to the caller. -+ intptr_t* fp = os::Linux::ucontext_get_fp(uc); -+ intptr_t* sp = os::Linux::ucontext_get_sp(uc); -+ address pc = (address)(uc->uc_mcontext.__gregs[REG_LR] -+ - NativeInstruction::instruction_size); -+ *fr = frame(sp, fp, pc); -+ if (!fr->is_java_frame()) { -+ assert(fr->safe_for_sender(thread), "Safety check"); -+ assert(!fr->is_first_frame(), "Safety check"); -+ *fr = fr->java_sender(); -+ } -+ } -+ } -+ assert(fr->is_java_frame(), "Safety check"); -+ return true; -+} -+ - // By default, gcc always saves frame pointer rfp on this stack. This - // may get turned off by -fomit-frame-pointer. - frame os::get_sender_for_C_frame(frame* fr) { - -From c1a03e0a376cc2c8748d83d66b576b66ee2e6962 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 16:14:19 +0800 -Subject: [PATCH 017/140] Revert JDK-8202579: Revisit VM_Version and - VM_Version_ext for overlap and consolidation - ---- - .../cpu/riscv/vm_version_ext_riscv.cpp | 87 +++++++++++++++++++ - .../cpu/riscv/vm_version_ext_riscv.hpp | 55 ++++++++++++ - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 14 --- - 3 files changed, 142 insertions(+), 14 deletions(-) - create mode 100644 src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp - create mode 100644 src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp - -diff --git a/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp -new file mode 100644 -index 00000000000..6bdce51506e ---- /dev/null -+++ b/src/hotspot/cpu/riscv/vm_version_ext_riscv.cpp -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * 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 "memory/allocation.hpp" -+#include "memory/allocation.inline.hpp" -+#include "runtime/os.inline.hpp" -+#include "vm_version_ext_riscv.hpp" -+ -+// VM_Version_Ext statics -+int VM_Version_Ext::_no_of_threads = 0; -+int VM_Version_Ext::_no_of_cores = 0; -+int VM_Version_Ext::_no_of_sockets = 0; -+bool VM_Version_Ext::_initialized = false; -+char VM_Version_Ext::_cpu_name[CPU_TYPE_DESC_BUF_SIZE] = {0}; -+char VM_Version_Ext::_cpu_desc[CPU_DETAILED_DESC_BUF_SIZE] = {0}; -+ -+void VM_Version_Ext::initialize_cpu_information(void) { -+ // do nothing if cpu info has been initialized -+ if (_initialized) { -+ return; -+ } -+ -+ _no_of_cores = os::processor_count(); -+ _no_of_threads = _no_of_cores; -+ _no_of_sockets = _no_of_cores; -+ snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64"); -+ snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string); -+ _initialized = true; -+} -+ -+int VM_Version_Ext::number_of_threads(void) { -+ initialize_cpu_information(); -+ return _no_of_threads; -+} -+ -+int VM_Version_Ext::number_of_cores(void) { -+ initialize_cpu_information(); -+ return _no_of_cores; -+} -+ -+int VM_Version_Ext::number_of_sockets(void) { -+ initialize_cpu_information(); -+ return _no_of_sockets; -+} -+ -+const char* VM_Version_Ext::cpu_name(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_TYPE_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_name, CPU_TYPE_DESC_BUF_SIZE); -+ return tmp; -+} -+ -+const char* VM_Version_Ext::cpu_description(void) { -+ initialize_cpu_information(); -+ char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_DETAILED_DESC_BUF_SIZE, mtTracing); -+ if (NULL == tmp) { -+ return NULL; -+ } -+ strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); -+ return tmp; -+} -diff --git a/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp -new file mode 100644 -index 00000000000..711e4aeaf68 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/vm_version_ext_riscv.hpp -@@ -0,0 +1,55 @@ -+/* -+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_VM_VERSION_EXT_RISCV_HPP -+#define CPU_RISCV_VM_VERSION_EXT_RISCV_HPP -+ -+#include "runtime/vm_version.hpp" -+#include "utilities/macros.hpp" -+ -+class VM_Version_Ext : public VM_Version { -+ private: -+ static const size_t CPU_TYPE_DESC_BUF_SIZE = 256; -+ static const size_t CPU_DETAILED_DESC_BUF_SIZE = 4096; -+ -+ static int _no_of_threads; -+ static int _no_of_cores; -+ static int _no_of_sockets; -+ static bool _initialized; -+ static char _cpu_name[CPU_TYPE_DESC_BUF_SIZE]; -+ static char _cpu_desc[CPU_DETAILED_DESC_BUF_SIZE]; -+ -+ public: -+ static int number_of_threads(void); -+ static int number_of_cores(void); -+ static int number_of_sockets(void); -+ -+ static const char* cpu_name(void); -+ static const char* cpu_description(void); -+ static void initialize_cpu_information(void); -+ -+}; -+ -+#endif // CPU_RISCV_VM_VERSION_EXT_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index 2c15a834542..dd65f32277f 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -210,17 +210,3 @@ void VM_Version::c2_initialize() { - } - } - #endif // COMPILER2 -- --void VM_Version::initialize_cpu_information(void) { -- // do nothing if cpu info has been initialized -- if (_initialized) { -- return; -- } -- -- _no_of_cores = os::processor_count(); -- _no_of_threads = _no_of_cores; -- _no_of_sockets = _no_of_cores; -- snprintf(_cpu_name, CPU_TYPE_DESC_BUF_SIZE - 1, "RISCV64"); -- snprintf(_cpu_desc, CPU_DETAILED_DESC_BUF_SIZE, "RISCV64 %s", _features_string); -- _initialized = true; --} - -From 0cfdbd8595c710b71be008bb531b59acf9c4b016 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 17:16:05 +0800 -Subject: [PATCH 018/140] Revert JDK-8191278: MappedByteBuffer bulk access - memory failures are not handled gracefully - ---- - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 19 ++----------------- - 1 file changed, 2 insertions(+), 17 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index 39416441bdf..8392b768847 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -1049,12 +1049,7 @@ class StubGenerator: public StubCodeGenerator { - __ push_reg(RegSet::of(d, count), sp); - } - -- { -- // UnsafeCopyMemory page error: continue after ucm -- bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); -- UnsafeCopyMemoryMark ucmm(this, add_entry, true); -- copy_memory(aligned, s, d, count, t0, size); -- } -+ copy_memory(aligned, s, d, count, t0, size); - - if (is_oop) { - __ pop_reg(RegSet::of(d, count), sp); -@@ -1122,12 +1117,7 @@ class StubGenerator: public StubCodeGenerator { - __ push_reg(RegSet::of(d, count), sp); - } - -- { -- // UnsafeCopyMemory page error: continue after ucm -- bool add_entry = !is_oop && (!aligned || sizeof(jlong) == size); -- UnsafeCopyMemoryMark ucmm(this, add_entry, true); -- copy_memory(aligned, s, d, count, t0, -size); -- } -+ copy_memory(aligned, s, d, count, t0, -size); - - if (is_oop) { - __ pop_reg(RegSet::of(d, count), sp); -@@ -3734,11 +3724,6 @@ class StubGenerator: public StubCodeGenerator { - ~StubGenerator() {} - }; // end class declaration - --#define UCM_TABLE_MAX_ENTRIES 8 - void StubGenerator_generate(CodeBuffer* code, bool all) { -- if (UnsafeCopyMemory::_table == NULL) { -- UnsafeCopyMemory::create_table(UCM_TABLE_MAX_ENTRIES); -- } -- - StubGenerator g(code, all); - } - -From dd6a7c520a5adeef5b6686c161554adcba61113f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 15:55:09 +0800 -Subject: [PATCH 019/140] Revert JDK-8282085: The REGISTER_DEFINITION macro is - useless after JDK-8269122 - ---- - .../cpu/riscv/register_definitions_riscv.cpp | 192 ++++++++++++++++++ - 1 file changed, 192 insertions(+) - create mode 100644 src/hotspot/cpu/riscv/register_definitions_riscv.cpp - -diff --git a/src/hotspot/cpu/riscv/register_definitions_riscv.cpp b/src/hotspot/cpu/riscv/register_definitions_riscv.cpp -new file mode 100644 -index 00000000000..583f67573ca ---- /dev/null -+++ b/src/hotspot/cpu/riscv/register_definitions_riscv.cpp -@@ -0,0 +1,192 @@ -+/* -+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2014, Red Hat Inc. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#include "precompiled.hpp" -+#include "asm/assembler.hpp" -+#include "asm/register.hpp" -+#include "interp_masm_riscv.hpp" -+#include "register_riscv.hpp" -+ -+REGISTER_DEFINITION(Register, noreg); -+ -+REGISTER_DEFINITION(Register, x0); -+REGISTER_DEFINITION(Register, x1); -+REGISTER_DEFINITION(Register, x2); -+REGISTER_DEFINITION(Register, x3); -+REGISTER_DEFINITION(Register, x4); -+REGISTER_DEFINITION(Register, x5); -+REGISTER_DEFINITION(Register, x6); -+REGISTER_DEFINITION(Register, x7); -+REGISTER_DEFINITION(Register, x8); -+REGISTER_DEFINITION(Register, x9); -+REGISTER_DEFINITION(Register, x10); -+REGISTER_DEFINITION(Register, x11); -+REGISTER_DEFINITION(Register, x12); -+REGISTER_DEFINITION(Register, x13); -+REGISTER_DEFINITION(Register, x14); -+REGISTER_DEFINITION(Register, x15); -+REGISTER_DEFINITION(Register, x16); -+REGISTER_DEFINITION(Register, x17); -+REGISTER_DEFINITION(Register, x18); -+REGISTER_DEFINITION(Register, x19); -+REGISTER_DEFINITION(Register, x20); -+REGISTER_DEFINITION(Register, x21); -+REGISTER_DEFINITION(Register, x22); -+REGISTER_DEFINITION(Register, x23); -+REGISTER_DEFINITION(Register, x24); -+REGISTER_DEFINITION(Register, x25); -+REGISTER_DEFINITION(Register, x26); -+REGISTER_DEFINITION(Register, x27); -+REGISTER_DEFINITION(Register, x28); -+REGISTER_DEFINITION(Register, x29); -+REGISTER_DEFINITION(Register, x30); -+REGISTER_DEFINITION(Register, x31); -+ -+REGISTER_DEFINITION(FloatRegister, fnoreg); -+ -+REGISTER_DEFINITION(FloatRegister, f0); -+REGISTER_DEFINITION(FloatRegister, f1); -+REGISTER_DEFINITION(FloatRegister, f2); -+REGISTER_DEFINITION(FloatRegister, f3); -+REGISTER_DEFINITION(FloatRegister, f4); -+REGISTER_DEFINITION(FloatRegister, f5); -+REGISTER_DEFINITION(FloatRegister, f6); -+REGISTER_DEFINITION(FloatRegister, f7); -+REGISTER_DEFINITION(FloatRegister, f8); -+REGISTER_DEFINITION(FloatRegister, f9); -+REGISTER_DEFINITION(FloatRegister, f10); -+REGISTER_DEFINITION(FloatRegister, f11); -+REGISTER_DEFINITION(FloatRegister, f12); -+REGISTER_DEFINITION(FloatRegister, f13); -+REGISTER_DEFINITION(FloatRegister, f14); -+REGISTER_DEFINITION(FloatRegister, f15); -+REGISTER_DEFINITION(FloatRegister, f16); -+REGISTER_DEFINITION(FloatRegister, f17); -+REGISTER_DEFINITION(FloatRegister, f18); -+REGISTER_DEFINITION(FloatRegister, f19); -+REGISTER_DEFINITION(FloatRegister, f20); -+REGISTER_DEFINITION(FloatRegister, f21); -+REGISTER_DEFINITION(FloatRegister, f22); -+REGISTER_DEFINITION(FloatRegister, f23); -+REGISTER_DEFINITION(FloatRegister, f24); -+REGISTER_DEFINITION(FloatRegister, f25); -+REGISTER_DEFINITION(FloatRegister, f26); -+REGISTER_DEFINITION(FloatRegister, f27); -+REGISTER_DEFINITION(FloatRegister, f28); -+REGISTER_DEFINITION(FloatRegister, f29); -+REGISTER_DEFINITION(FloatRegister, f30); -+REGISTER_DEFINITION(FloatRegister, f31); -+ -+REGISTER_DEFINITION(VectorRegister, vnoreg); -+ -+REGISTER_DEFINITION(VectorRegister, v0); -+REGISTER_DEFINITION(VectorRegister, v1); -+REGISTER_DEFINITION(VectorRegister, v2); -+REGISTER_DEFINITION(VectorRegister, v3); -+REGISTER_DEFINITION(VectorRegister, v4); -+REGISTER_DEFINITION(VectorRegister, v5); -+REGISTER_DEFINITION(VectorRegister, v6); -+REGISTER_DEFINITION(VectorRegister, v7); -+REGISTER_DEFINITION(VectorRegister, v8); -+REGISTER_DEFINITION(VectorRegister, v9); -+REGISTER_DEFINITION(VectorRegister, v10); -+REGISTER_DEFINITION(VectorRegister, v11); -+REGISTER_DEFINITION(VectorRegister, v12); -+REGISTER_DEFINITION(VectorRegister, v13); -+REGISTER_DEFINITION(VectorRegister, v14); -+REGISTER_DEFINITION(VectorRegister, v15); -+REGISTER_DEFINITION(VectorRegister, v16); -+REGISTER_DEFINITION(VectorRegister, v17); -+REGISTER_DEFINITION(VectorRegister, v18); -+REGISTER_DEFINITION(VectorRegister, v19); -+REGISTER_DEFINITION(VectorRegister, v20); -+REGISTER_DEFINITION(VectorRegister, v21); -+REGISTER_DEFINITION(VectorRegister, v22); -+REGISTER_DEFINITION(VectorRegister, v23); -+REGISTER_DEFINITION(VectorRegister, v24); -+REGISTER_DEFINITION(VectorRegister, v25); -+REGISTER_DEFINITION(VectorRegister, v26); -+REGISTER_DEFINITION(VectorRegister, v27); -+REGISTER_DEFINITION(VectorRegister, v28); -+REGISTER_DEFINITION(VectorRegister, v29); -+REGISTER_DEFINITION(VectorRegister, v30); -+REGISTER_DEFINITION(VectorRegister, v31); -+ -+REGISTER_DEFINITION(Register, c_rarg0); -+REGISTER_DEFINITION(Register, c_rarg1); -+REGISTER_DEFINITION(Register, c_rarg2); -+REGISTER_DEFINITION(Register, c_rarg3); -+REGISTER_DEFINITION(Register, c_rarg4); -+REGISTER_DEFINITION(Register, c_rarg5); -+REGISTER_DEFINITION(Register, c_rarg6); -+REGISTER_DEFINITION(Register, c_rarg7); -+ -+REGISTER_DEFINITION(FloatRegister, c_farg0); -+REGISTER_DEFINITION(FloatRegister, c_farg1); -+REGISTER_DEFINITION(FloatRegister, c_farg2); -+REGISTER_DEFINITION(FloatRegister, c_farg3); -+REGISTER_DEFINITION(FloatRegister, c_farg4); -+REGISTER_DEFINITION(FloatRegister, c_farg5); -+REGISTER_DEFINITION(FloatRegister, c_farg6); -+REGISTER_DEFINITION(FloatRegister, c_farg7); -+ -+REGISTER_DEFINITION(Register, j_rarg0); -+REGISTER_DEFINITION(Register, j_rarg1); -+REGISTER_DEFINITION(Register, j_rarg2); -+REGISTER_DEFINITION(Register, j_rarg3); -+REGISTER_DEFINITION(Register, j_rarg4); -+REGISTER_DEFINITION(Register, j_rarg5); -+REGISTER_DEFINITION(Register, j_rarg6); -+REGISTER_DEFINITION(Register, j_rarg7); -+ -+REGISTER_DEFINITION(FloatRegister, j_farg0); -+REGISTER_DEFINITION(FloatRegister, j_farg1); -+REGISTER_DEFINITION(FloatRegister, j_farg2); -+REGISTER_DEFINITION(FloatRegister, j_farg3); -+REGISTER_DEFINITION(FloatRegister, j_farg4); -+REGISTER_DEFINITION(FloatRegister, j_farg5); -+REGISTER_DEFINITION(FloatRegister, j_farg6); -+REGISTER_DEFINITION(FloatRegister, j_farg7); -+ -+REGISTER_DEFINITION(Register, zr); -+REGISTER_DEFINITION(Register, gp); -+REGISTER_DEFINITION(Register, tp); -+REGISTER_DEFINITION(Register, xmethod); -+REGISTER_DEFINITION(Register, ra); -+REGISTER_DEFINITION(Register, sp); -+REGISTER_DEFINITION(Register, fp); -+REGISTER_DEFINITION(Register, xheapbase); -+REGISTER_DEFINITION(Register, xcpool); -+REGISTER_DEFINITION(Register, xmonitors); -+REGISTER_DEFINITION(Register, xlocals); -+REGISTER_DEFINITION(Register, xthread); -+REGISTER_DEFINITION(Register, xbcp); -+REGISTER_DEFINITION(Register, xdispatch); -+REGISTER_DEFINITION(Register, esp); -+ -+REGISTER_DEFINITION(Register, t0); -+REGISTER_DEFINITION(Register, t1); -+REGISTER_DEFINITION(Register, t2); - -From 561261b051d88ddb0053733f03cbefc75dedcea8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 16:41:03 +0800 -Subject: [PATCH 020/140] Revert JDK-7175279: Don't use x87 FPU on x86-64 - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 0e383a3c139..977563fe5f4 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -2019,6 +2019,18 @@ address LIR_Assembler::int_constant(jlong n) { - } - } - -+void LIR_Assembler::set_24bit_FPU() { Unimplemented(); } -+ -+void LIR_Assembler::reset_FPU() { Unimplemented(); } -+ -+void LIR_Assembler::fpop() { Unimplemented(); } -+ -+void LIR_Assembler::fxch(int i) { Unimplemented(); } -+ -+void LIR_Assembler::fld(int i) { Unimplemented(); } -+ -+void LIR_Assembler::ffree(int i) { Unimplemented(); } -+ - void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { - __ cmpxchg(addr, cmpval, newval, Assembler::int32, Assembler::aq /* acquire */, - Assembler::rl /* release */, t0, true /* result as bool */); - -From ff4e1443fd000208714b506d52c0fab1c91e4ac8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 16:41:15 +0800 -Subject: [PATCH 021/140] Revert JDK-8255909: Remove unused delayed_value - methods - ---- - src/hotspot/cpu/riscv/assembler_riscv.hpp | 7 +++++++ - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 16 ++++++++++++++++ - src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 4 ++++ - 3 files changed, 27 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp -index 4923962a496..44e8d4b4ff1 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -3027,6 +3027,13 @@ enum Nf { - Assembler(CodeBuffer* code) : AbstractAssembler(code), _in_compressible_region(false) { - } - -+ virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, -+ Register tmp, -+ int offset) { -+ ShouldNotCallThis(); -+ return RegisterOrConstant(); -+ } -+ - // Stack overflow checking - virtual void bang_stack_with_offset(int offset) { Unimplemented(); } - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 269d76ba69e..878957cbede 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -191,6 +191,22 @@ void MacroAssembler::call_VM(Register oop_result, - void MacroAssembler::check_and_handle_earlyret(Register java_thread) {} - void MacroAssembler::check_and_handle_popframe(Register java_thread) {} - -+RegisterOrConstant MacroAssembler::delayed_value_impl(intptr_t* delayed_value_addr, -+ Register tmp, -+ int offset) { -+ intptr_t value = *delayed_value_addr; -+ if (value != 0) -+ return RegisterOrConstant(value + offset); -+ -+ // load indirectly to solve generation ordering problem -+ ld(tmp, ExternalAddress((address) delayed_value_addr)); -+ -+ if (offset != 0) -+ add(tmp, tmp, offset); -+ -+ return RegisterOrConstant(tmp); -+} -+ - // Calls to C land - // - // When entering C land, the fp, & esp of the last Java frame have to be recorded -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index b59bdadb8bf..f23f7e7d1e6 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -625,6 +625,10 @@ class MacroAssembler: public Assembler { - - void reserved_stack_check(); - -+ virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, -+ Register tmp, -+ int offset); -+ - void get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype); - void read_polling_page(Register r, address page, relocInfo::relocType rtype); - void read_polling_page(Register r, int32_t offset, relocInfo::relocType rtype); - -From afe35a3fdc705645bfe2a2e797a95ce1d5203872 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 16:51:39 +0800 -Subject: [PATCH 022/140] Revert JDK-8263679: C1: Remove vtable call - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 977563fe5f4..a0ecc63d851 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -1382,6 +1382,11 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { - add_call_info(code_offset(), op->info()); - } - -+/* Currently, vtable-dispatch is only enabled for sparc platforms */ -+void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { -+ ShouldNotReachHere(); -+} -+ - void LIR_Assembler::emit_static_call_stub() { - address call_pc = __ pc(); - assert((__ offset() % 4) == 0, "bad alignment"); - -From 655b34c00ec5ff6fa7e82de96a78a0c58ba91985 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 16:55:57 +0800 -Subject: [PATCH 023/140] Revert JDK-8264063: Outer Safepoint poll load should - not reference the head of inner strip mined loop. - ---- - src/hotspot/cpu/riscv/riscv.ad | 14 ++++++++++++++ - 1 file changed, 14 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 8c7a8ede815..fcddf752564 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -952,6 +952,20 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const - return align_up(current_offset, alignment_required()) - current_offset; - } - -+// Indicate if the safepoint node needs the polling page as an input -+ -+// the shared code plants the oop data at the start of the generated -+// code for the safepoint node and that needs ot be at the load -+// instruction itself. so we cannot plant a mov of the safepoint poll -+// address followed by a load. setting this to true means the mov is -+// scheduled as a prior instruction. that's better for scheduling -+// anyway. -+ -+bool SafePointNode::needs_polling_address_input() -+{ -+ return true; -+} -+ - //============================================================================= - - #ifndef PRODUCT - -From 4a6f7dafdb4e0cf054b7867de60f789d4ca1d9f3 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:26:29 +0800 -Subject: [PATCH 024/140] Revert: JDK-8266810: Move trivial Matcher code to - cpu-specific header files JDK-8254966: Remove unused code from Matcher - ---- - src/hotspot/cpu/riscv/matcher_riscv.hpp | 129 ------------------------ - src/hotspot/cpu/riscv/riscv.ad | 108 +++++++++++++++++++- - 2 files changed, 107 insertions(+), 130 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/matcher_riscv.hpp - -diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp -deleted file mode 100644 -index 4c7fabd7240..00000000000 ---- a/src/hotspot/cpu/riscv/matcher_riscv.hpp -+++ /dev/null -@@ -1,129 +0,0 @@ --/* -- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2021, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef CPU_RISCV_MATCHER_RISCV_HPP --#define CPU_RISCV_MATCHER_RISCV_HPP -- -- // Defined within class Matcher -- -- // false => size gets scaled to BytesPerLong, ok. -- static const bool init_array_count_is_in_bytes = false; -- -- // riscv doesn't support misaligned vectors store/load on JDK11. -- static constexpr bool misaligned_vectors_ok() { -- return false; -- } -- -- // Whether code generation need accurate ConvI2L types. -- static const bool convi2l_type_required = false; -- -- // Does the CPU require late expand (see block.cpp for description of late expand)? -- static const bool require_postalloc_expand = false; -- -- // Do we need to mask the count passed to shift instructions or does -- // the cpu only look at the lower 5/6 bits anyway? -- static const bool need_masked_shift_count = false; -- -- static constexpr bool isSimpleConstant64(jlong value) { -- // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. -- // Probably always true, even if a temp register is required. -- return true; -- } -- -- // Use conditional move (CMOVL) -- static constexpr int long_cmove_cost() { -- // long cmoves are no more expensive than int cmoves -- return 0; -- } -- -- static constexpr int float_cmove_cost() { -- // float cmoves are no more expensive than int cmoves -- return 0; -- } -- -- // This affects two different things: -- // - how Decode nodes are matched -- // - how ImplicitNullCheck opportunities are recognized -- // If true, the matcher will try to remove all Decodes and match them -- // (as operands) into nodes. NullChecks are not prepared to deal with -- // Decodes by final_graph_reshaping(). -- // If false, final_graph_reshaping() forces the decode behind the Cmp -- // for a NullCheck. The matcher matches the Decode node into a register. -- // Implicit_null_check optimization moves the Decode along with the -- // memory operation back up before the NullCheck. -- static bool narrow_oop_use_complex_address() { -- return CompressedOops::shift() == 0; -- } -- -- static bool narrow_klass_use_complex_address() { -- return false; -- } -- -- static bool const_oop_prefer_decode() { -- // Prefer ConN+DecodeN over ConP in simple compressed oops mode. -- return CompressedOops::base() == NULL; -- } -- -- static bool const_klass_prefer_decode() { -- // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. -- return CompressedKlassPointers::base() == NULL; -- } -- -- // Is it better to copy float constants, or load them directly from -- // memory? Intel can load a float constant from a direct address, -- // requiring no extra registers. Most RISCs will have to materialize -- // an address into a register first, so they would do better to copy -- // the constant from stack. -- static const bool rematerialize_float_constants = false; -- -- // If CPU can load and store mis-aligned doubles directly then no -- // fixup is needed. Else we split the double into 2 integer pieces -- // and move it piece-by-piece. Only happens when passing doubles into -- // C code as the Java calling convention forces doubles to be aligned. -- static const bool misaligned_doubles_ok = true; -- -- // Advertise here if the CPU requires explicit rounding operations to implement strictfp mode. -- static const bool strict_fp_requires_explicit_rounding = false; -- -- // Are floats converted to double when stored to stack during -- // deoptimization? -- static constexpr bool float_in_double() { return false; } -- -- // Do ints take an entire long register or just half? -- // The relevant question is how the int is callee-saved: -- // the whole long is written but de-opt'ing will have to extract -- // the relevant 32 bits. -- static const bool int_in_long = true; -- -- // true means we have fast l2f convers -- // false means that conversion is done by runtime call -- static constexpr bool convL2FSupported(void) { -- return true; -- } -- -- // Implements a variant of EncodeISOArrayNode that encode ASCII only -- static const bool supports_encode_ascii_array = false; -- --#endif // CPU_RISCV_MATCHER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index fcddf752564..a9e5f2e6841 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -330,7 +330,9 @@ alloc_class chunk2(RFLAGS); - // Several register classes are automatically defined based upon information in - // this architecture description. - // 1) reg_class inline_cache_reg ( /* as def'd in frame section */ ) --// 2) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) -+// 2) reg_class compiler_method_reg ( /* as def'd in frame section */ ) -+// 2) reg_class interpreter_method_reg ( /* as def'd in frame section */ ) -+// 3) reg_class stack_slots( /* one chunk of stack-based "registers" */ ) - // - - // Class for all 32 bit general purpose registers -@@ -1548,6 +1550,17 @@ bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) { - return (-4096 <= offs && offs < 4096); - } - -+const bool Matcher::isSimpleConstant64(jlong value) { -+ // Will one (StoreL ConL) be cheaper than two (StoreI ConI)?. -+ // Probably always true, even if a temp register is required. -+ return true; -+} -+ -+// true just means we have fast l2f conversion -+const bool Matcher::convL2FSupported(void) { -+ return true; -+} -+ - // Vector width in bytes. - const int Matcher::vector_width_in_bytes(BasicType bt) { - return 0; -@@ -1567,6 +1580,94 @@ const uint Matcher::vector_ideal_reg(int len) { - return 0; - } - -+// RISC-V supports misaligned vectors store/load. -+const bool Matcher::misaligned_vectors_ok() { -+ return true; -+} -+ -+// false => size gets scaled to BytesPerLong, ok. -+const bool Matcher::init_array_count_is_in_bytes = false; -+ -+// Use conditional move (CMOVL) -+const int Matcher::long_cmove_cost() { -+ // long cmoves are no more expensive than int cmoves -+ return 0; -+} -+ -+const int Matcher::float_cmove_cost() { -+ // float cmoves are no more expensive than int cmoves -+ return 0; -+} -+ -+// Does the CPU require late expand (see block.cpp for description of late expand)? -+const bool Matcher::require_postalloc_expand = false; -+ -+// Do we need to mask the count passed to shift instructions or does -+// the cpu only look at the lower 5/6 bits anyway? -+const bool Matcher::need_masked_shift_count = false; -+ -+// This affects two different things: -+// - how Decode nodes are matched -+// - how ImplicitNullCheck opportunities are recognized -+// If true, the matcher will try to remove all Decodes and match them -+// (as operands) into nodes. NullChecks are not prepared to deal with -+// Decodes by final_graph_reshaping(). -+// If false, final_graph_reshaping() forces the decode behind the Cmp -+// for a NullCheck. The matcher matches the Decode node into a register. -+// Implicit_null_check optimization moves the Decode along with the -+// memory operation back up before the NullCheck. -+bool Matcher::narrow_oop_use_complex_address() { -+ return Universe::narrow_oop_shift() == 0; -+} -+ -+bool Matcher::narrow_klass_use_complex_address() { -+// TODO -+// decide whether we need to set this to true -+ return false; -+} -+ -+bool Matcher::const_oop_prefer_decode() { -+ // Prefer ConN+DecodeN over ConP in simple compressed oops mode. -+ return Universe::narrow_oop_base() == NULL; -+} -+ -+bool Matcher::const_klass_prefer_decode() { -+ // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. -+ return Universe::narrow_klass_base() == NULL; -+} -+ -+// Is it better to copy float constants, or load them directly from -+// memory? Intel can load a float constant from a direct address, -+// requiring no extra registers. Most RISCs will have to materialize -+// an address into a register first, so they would do better to copy -+// the constant from stack. -+const bool Matcher::rematerialize_float_constants = false; -+ -+// If CPU can load and store mis-aligned doubles directly then no -+// fixup is needed. Else we split the double into 2 integer pieces -+// and move it piece-by-piece. Only happens when passing doubles into -+// C code as the Java calling convention forces doubles to be aligned. -+const bool Matcher::misaligned_doubles_ok = true; -+ -+// No-op on amd64 -+void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { -+ Unimplemented(); -+} -+ -+// Advertise here if the CPU requires explicit rounding operations to -+// implement the UseStrictFP mode. -+const bool Matcher::strict_fp_requires_explicit_rounding = false; -+ -+// Are floats converted to double when stored to stack during -+// deoptimization? -+bool Matcher::float_in_double() { return false; } -+ -+// Do ints take an entire long register or just half? -+// The relevant question is how the int is callee-saved: -+// the whole long is written but de-opt'ing will have to extract -+// the relevant 32 bits. -+const bool Matcher::int_in_long = true; -+ - // Return whether or not this register is ever used as an argument. - // This function is used on startup to build the trampoline stubs in - // generateOptoStub. Registers not mentioned will be killed by the VM -@@ -1671,6 +1772,8 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) { - return true; - } - -+const bool Matcher::convi2l_type_required = false; -+ - // Should the Matcher clone input 'm' of node 'n'? - bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { - assert_cond(m != NULL); -@@ -2250,6 +2353,9 @@ frame %{ - // Inline Cache Register or methodOop for I2C. - inline_cache_reg(R31); - -+ // Method Oop Register when calling interpreter. -+ interpreter_method_oop_reg(R31); -+ - // Optional: name the operand used by cisc-spilling to access [stack_pointer + offset] - cisc_spilling_operand_name(indOffset); - - -From 4b0f20882cd9b5e5da92d61c2fa02e0cbea0ef0c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:30:42 +0800 -Subject: [PATCH 025/140] Revert JDK-8256238: Remove - Matcher::pass_original_key_for_aes - ---- - src/hotspot/cpu/riscv/riscv.ad | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index a9e5f2e6841..0d1afd5584a 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1580,6 +1580,11 @@ const uint Matcher::vector_ideal_reg(int len) { - return 0; - } - -+// AES support not yet implemented -+const bool Matcher::pass_original_key_for_aes() { -+ return false; -+} -+ - // RISC-V supports misaligned vectors store/load. - const bool Matcher::misaligned_vectors_ok() { - return true; - -From 36d7ecedbcd95911d1b355bbab3e8fdf81b36e7d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:42:37 +0800 -Subject: [PATCH 026/140] Revert JDK-8242492: C2: Remove - Matcher::vector_shift_count_ideal_reg() - ---- - src/hotspot/cpu/riscv/riscv.ad | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 0d1afd5584a..c10e91633a5 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1580,6 +1580,11 @@ const uint Matcher::vector_ideal_reg(int len) { - return 0; - } - -+const uint Matcher::vector_shift_count_ideal_reg(int size) { -+ fatal("vector shift is not supported"); -+ return Node::NotAMachineReg; -+} -+ - // AES support not yet implemented - const bool Matcher::pass_original_key_for_aes() { - return false; - -From b78e448a460fcdc66553e66342e93e5ac87c0c61 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:47:13 +0800 -Subject: [PATCH 027/140] Revert JDK-8266937: Remove Compile::reshape_address - ---- - src/hotspot/cpu/riscv/riscv.ad | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c10e91633a5..2c5ec0451b8 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1801,6 +1801,9 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, - return clone_base_plus_offset_address(m, mstack, address_visited); - } - -+void Compile::reshape_address(AddPNode* addp) { -+} -+ - %} - - - -From cd34a5ce5d120cdac939217976d1e7b7e98bf654 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:49:09 +0800 -Subject: [PATCH 028/140] Revert JDK-8272771: frame::pd_ps() is not implemented - on any platform - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 8e7babe2c61..8e4f20fe561 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -683,6 +683,7 @@ frame::frame(void* ptr_sp, void* ptr_fp, void* pc) { - init((intptr_t*)ptr_sp, (intptr_t*)ptr_fp, (address)pc); - } - -+void frame::pd_ps() {} - #endif - - void JavaFrameAnchor::make_walkable(JavaThread* thread) { - -From bdb16daf6d809d0c38256be99ecbe922d24b889b Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:56:27 +0800 -Subject: [PATCH 029/140] Revert JDK-8268858: Determine register pressure - automatically by the number of available registers for allocation - ---- - src/hotspot/cpu/riscv/riscv.ad | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 2c5ec0451b8..a6aa52de29e 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1527,6 +1527,10 @@ const bool Matcher::has_predicated_vectors(void) { - return false; - } - -+const int Matcher::float_pressure(int default_pressure_threshold) { -+ return default_pressure_threshold; -+} -+ - // Is this branch offset short enough that a short branch can be used? - // - // NOTE: If the platform does not provide any short branch variants, then - -From bbaa7a97b5d8110ead9dc44f31e2c5fe3bcd83d5 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 17:58:16 +0800 -Subject: [PATCH 030/140] Revert JDK-8253040: Remove unused - Matcher::regnum_to_fpu_offset() - ---- - src/hotspot/cpu/riscv/riscv.ad | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index a6aa52de29e..2d847cb6454 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1531,6 +1531,12 @@ const int Matcher::float_pressure(int default_pressure_threshold) { - return default_pressure_threshold; - } - -+int Matcher::regnum_to_fpu_offset(int regnum) -+{ -+ Unimplemented(); -+ return 0; -+} -+ - // Is this branch offset short enough that a short branch can be used? - // - // NOTE: If the platform does not provide any short branch variants, then - -From ce9ad0af72e405153534369bff1b1725697f3e40 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 18:03:23 +0800 -Subject: [PATCH 031/140] Revert JDK-8254084: Remove - TemplateTable::pd_initialize - ---- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index 4e388ac4eaa..c9d399ccdaf 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -48,6 +48,12 @@ - - #define __ _masm-> - -+// Platform-dependent initialization -+ -+void TemplateTable::pd_initialize() { -+ // No RISC-V specific initialization -+} -+ - // Address computation: local variables - - static inline Address iaddress(int n) { - -From 49429187846e6f2b00ab2853e27097eae274a947 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 20:17:07 +0800 -Subject: [PATCH 032/140] Revert JDK-8224815: 8224815: Remove non-GC uses of - CollectedHeap::is_in_reserved() - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 878957cbede..cf01d7d74bb 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1632,7 +1632,7 @@ void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) { - #ifdef ASSERT - { - ThreadInVMfromUnknown tiv; -- assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); -+ assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "should be real oop"); - } - #endif - oop_index = oop_recorder()->find_index(obj); -@@ -2800,7 +2800,7 @@ void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { - assert (UseCompressedOops, "should only be used for compressed oops"); - assert (Universe::heap() != NULL, "java heap should be initialized"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); -- assert(Universe::heap()->is_in(JNIHandles::resolve(obj)), "should be real oop"); -+ assert(Universe::heap()->is_in_reserved(JNIHandles::resolve(obj)), "should be real oop"); - } - #endif - int oop_index = oop_recorder()->find_index(obj); -@@ -2815,7 +2815,7 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedClassPointers, "should only be used for compressed headers"); - assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); - int index = oop_recorder()->find_index(k); -- assert(!Universe::heap()->is_in(k), "should not be an oop"); -+ assert(!Universe::heap()->is_in_reserved(k), "should not be an oop"); - - InstructionMark im(this); - RelocationHolder rspec = metadata_Relocation::spec(index); - -From a71fabb1ff05db9955557a888be6cd1b5f87deea Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 21:14:30 +0800 -Subject: [PATCH 033/140] Revert JDK-8253540: InterpreterRuntime::monitorexit - should be a JRT_LEAF function - ---- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 8adc7b1320d..48957803fdc 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -839,7 +839,9 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) - assert(lock_reg == c_rarg1, "The argument is only for looks. It must be rarg1"); - - if (UseHeavyMonitors) { -- call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); -+ call_VM(noreg, -+ CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), -+ lock_reg); - } else { - Label done; - -@@ -871,7 +873,9 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) - - // Call the runtime routine for slow case. - sd(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // restore obj -- call_VM_leaf(CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), lock_reg); -+ call_VM(noreg, -+ CAST_FROM_FN_PTR(address, InterpreterRuntime::monitorexit), -+ lock_reg); - - bind(done); - - -From a0b18eea3c83ef8f1de2c1b3cd55452f0f6b9af2 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Fri, 7 Apr 2023 12:51:33 +0800 -Subject: [PATCH 034/140] Revert JDK-8278387: riscv: Implement UseHeavyMonitors - consistently && JDK-8279826: riscv: Preserve result in native wrapper with - +UseHeavyMonitors - ---- - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 8 +- - src/hotspot/cpu/riscv/riscv.ad | 92 +++++++++---------- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 85 ++++++++--------- - 3 files changed, 80 insertions(+), 105 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index a0ecc63d851..dd657963438 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -367,11 +367,7 @@ int LIR_Assembler::emit_unwind_handler() { - if (method()->is_synchronized()) { - monitor_address(0, FrameMap::r10_opr); - stub = new MonitorExitStub(FrameMap::r10_opr, true, 0); -- if (UseHeavyMonitors) { -- __ j(*stub->entry()); -- } else { -- __ unlock_object(x15, x14, x10, *stub->entry()); -- } -+ __ unlock_object(x15, x14, x10, *stub->entry()); - __ bind(*stub->continuation()); - } - -@@ -1512,7 +1508,7 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { - Register obj = op->obj_opr()->as_register(); // may not be an oop - Register hdr = op->hdr_opr()->as_register(); - Register lock = op->lock_opr()->as_register(); -- if (UseHeavyMonitors) { -+ if (!UseFastLocking) { - __ j(*op->stub()->entry()); - } else if (op->code() == lir_lock) { - assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 2d847cb6454..29027d594a0 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2109,40 +2109,36 @@ encode %{ - __ andi(t0, disp_hdr, markOopDesc::monitor_value); - __ bnez(t0, object_has_monitor); - -- if (!UseHeavyMonitors) { -- // Set tmp to be (markWord of object | UNLOCK_VALUE). -- __ ori(tmp, disp_hdr, markOopDesc::unlocked_value); -- -- // Initialize the box. (Must happen before we update the object mark!) -- __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -- -- // Compare object markWord with an unlocked value (tmp) and if -- // equal exchange the stack address of our box with object markWord. -- // On failure disp_hdr contains the possibly locked markWord. -- __ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq, -- Assembler::rl, /*result*/disp_hdr); -- __ mv(flag, zr); -- __ beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas -- -- assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); -- -- // If the compare-and-exchange succeeded, then we found an unlocked -- // object, will have now locked it will continue at label cont -- // We did not see an unlocked object so try the fast recursive case. -- -- // Check if the owner is self by comparing the value in the -- // markWord of object (disp_hdr) with the stack pointer. -- __ sub(disp_hdr, disp_hdr, sp); -- __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markOopDesc::lock_mask_in_place)); -- // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, -- // hence we can store 0 as the displaced header in the box, which indicates that it is a -- // recursive lock. -- __ andr(tmp/*==0?*/, disp_hdr, tmp); -- __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); -- __ mv(flag, tmp); // we can use the value of tmp as the result here -- } else { -- __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow-path -- } -+ // Set tmp to be (markWord of object | UNLOCK_VALUE). -+ __ ori(tmp, disp_hdr, markOopDesc::unlocked_value); -+ -+ // Initialize the box. (Must happen before we update the object mark!) -+ __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ -+ // Compare object markWord with an unlocked value (tmp) and if -+ // equal exchange the stack address of our box with object markWord. -+ // On failure disp_hdr contains the possibly locked markWord. -+ __ cmpxchg(/*memory address*/oop, /*expected value*/tmp, /*new value*/box, Assembler::int64, Assembler::aq, -+ Assembler::rl, /*result*/disp_hdr); -+ __ mv(flag, zr); -+ __ beq(disp_hdr, tmp, cont); // prepare zero flag and goto cont if we won the cas -+ -+ assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); -+ -+ // If the compare-and-exchange succeeded, then we found an unlocked -+ // object, will have now locked it will continue at label cont -+ // We did not see an unlocked object so try the fast recursive case. -+ -+ // Check if the owner is self by comparing the value in the -+ // markWord of object (disp_hdr) with the stack pointer. -+ __ sub(disp_hdr, disp_hdr, sp); -+ __ li(tmp, (intptr_t) (~(os::vm_page_size()-1) | (uintptr_t)markOopDesc::lock_mask_in_place)); -+ // If (mark & lock_mask) == 0 and mark - sp < page_size, we are stack-locking and goto cont, -+ // hence we can store 0 as the displaced header in the box, which indicates that it is a -+ // recursive lock. -+ __ andr(tmp/*==0?*/, disp_hdr, tmp); -+ __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ __ mv(flag, tmp); // we can use the value of tmp as the result here - - __ j(cont); - -@@ -2189,31 +2185,25 @@ encode %{ - - assert_different_registers(oop, box, tmp, disp_hdr, flag); - -- if (!UseHeavyMonitors) { -- // Find the lock address and load the displaced header from the stack. -- __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ // Find the lock address and load the displaced header from the stack. -+ __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); - -- // If the displaced header is 0, we have a recursive unlock. -- __ mv(flag, disp_hdr); -- __ beqz(disp_hdr, cont); -- } -+ // If the displaced header is 0, we have a recursive unlock. -+ __ mv(flag, disp_hdr); -+ __ beqz(disp_hdr, cont); - - // Handle existing monitor. - __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); - __ andi(t0, disp_hdr, markOopDesc::monitor_value); - __ bnez(t0, object_has_monitor); - -- if (!UseHeavyMonitors) { -- // Check if it is still a light weight lock, this is true if we -- // see the stack address of the basicLock in the markWord of the -- // object. -+ // Check if it is still a light weight lock, this is true if we -+ // see the stack address of the basicLock in the markWord of the -+ // object. - -- __ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed, -- Assembler::rl, /*result*/tmp); -- __ xorr(flag, box, tmp); // box == tmp if cas succeeds -- } else { -- __ mv(flag, 1); // Set non-zero flag to indicate 'failure' -> take slow path -- } -+ __ cmpxchg(/*memory address*/oop, /*expected value*/box, /*new value*/disp_hdr, Assembler::int64, Assembler::relaxed, -+ Assembler::rl, /*result*/tmp); -+ __ xorr(flag, box, tmp); // box == tmp if cas succeeds - __ j(cont); - - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 21aa3b58c09..5203200b068 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1488,39 +1488,35 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - // Load the oop from the handle - __ ld(obj_reg, Address(oop_handle_reg, 0)); - -- if (!UseHeavyMonitors) { -- // Load (object->mark() | 1) into swap_reg % x10 -- __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); -- __ ori(swap_reg, t0, 1); -- -- // Save (object->mark() | 1) into BasicLock's displaced header -- __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -- -- // src -> dest if dest == x10 else x10 <- dest -- { -- Label here; -- __ cmpxchg_obj_header(x10, lock_reg, obj_reg, t0, lock_done, /*fallthrough*/NULL); -- } -+ // Load (object->mark() | 1) into swap_reg % x10 -+ __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); -+ __ ori(swap_reg, t0, 1); - -- // Test if the oopMark is an obvious stack pointer, i.e., -- // 1) (mark & 3) == 0, and -- // 2) sp <= mark < mark + os::pagesize() -- // These 3 tests can be done by evaluating the following -- // expression: ((mark - sp) & (3 - os::vm_page_size())), -- // assuming both stack pointer and pagesize have their -- // least significant 2 bits clear. -- // NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg -- -- __ sub(swap_reg, swap_reg, sp); -- __ andi(swap_reg, swap_reg, 3 - os::vm_page_size()); -- -- // Save the test result, for recursive case, the result is zero -- __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -- __ bnez(swap_reg, slow_path_lock); -- } else { -- __ j(slow_path_lock); -+ // Save (object->mark() | 1) into BasicLock's displaced header -+ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -+ -+ // src -> dest if dest == x10 else x10 <- dest -+ { -+ Label here; -+ __ cmpxchg_obj_header(x10, lock_reg, obj_reg, t0, lock_done, /*fallthrough*/NULL); - } - -+ // Test if the oopMark is an obvious stack pointer, i.e., -+ // 1) (mark & 3) == 0, and -+ // 2) sp <= mark < mark + os::pagesize() -+ // These 3 tests can be done by evaluating the following -+ // expression: ((mark - sp) & (3 - os::vm_page_size())), -+ // assuming both stack pointer and pagesize have their -+ // least significant 2 bits clear. -+ // NOTE: the oopMark is in swap_reg % 10 as the result of cmpxchg -+ -+ __ sub(swap_reg, swap_reg, sp); -+ __ andi(swap_reg, swap_reg, 3 - os::vm_page_size()); -+ -+ // Save the test result, for recursive case, the result is zero -+ __ sd(swap_reg, Address(lock_reg, mark_word_offset)); -+ __ bnez(swap_reg, slow_path_lock); -+ - // Slow path will re-enter here - __ bind(lock_done); - } -@@ -1608,31 +1604,24 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - - Label done; - -- if (!UseHeavyMonitors) { -- // Simple recursive lock? -- __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -- __ beqz(t0, done); -- } -- -+ // Simple recursive lock? -+ __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -+ __ beqz(t0, done); - - // Must save x10 if if it is live now because cmpxchg must use it - if (ret_type != T_FLOAT && ret_type != T_DOUBLE && ret_type != T_VOID) { - save_native_result(masm, ret_type, stack_slots); - } - -- if (!UseHeavyMonitors) { -- // get address of the stack lock -- __ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -- // get old displaced header -- __ ld(old_hdr, Address(x10, 0)); -+ // get address of the stack lock -+ __ la(x10, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); -+ // get old displaced header -+ __ ld(old_hdr, Address(x10, 0)); - -- // Atomic swap old header if oop still contains the stack lock -- Label succeed; -- __ cmpxchg_obj_header(x10, old_hdr, obj_reg, t0, succeed, &slow_path_unlock); -- __ bind(succeed); -- } else { -- __ j(slow_path_unlock); -- } -+ // Atomic swap old header if oop still contains the stack lock -+ Label succeed; -+ __ cmpxchg_obj_header(x10, old_hdr, obj_reg, t0, succeed, &slow_path_unlock); -+ __ bind(succeed); - - // slow path re-enters here - __ bind(unlock_done); - -From 1e844b8019cb3516c0843826de2bd3fcd2222f41 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 4 Apr 2023 16:49:19 +0800 -Subject: [PATCH 035/140] Revert JDK-8258192: Obsolete the CriticalJNINatives - flag. CriticalJNINatives is unimplemented() even on AArch64. See - https://bugs.openjdk.org/browse/JDK-8254694. - -Also following up 8191129: AARCH64: Invalid value passed to critical JNI function ---- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 3 ++- - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 2 ++ - .../criticalnatives/argumentcorruption/CheckLongArgs.java | 2 +- - .../jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java | 2 +- - 4 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 5203200b068..f8585afbdc2 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1111,7 +1111,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - int compile_id, - BasicType* in_sig_bt, - VMRegPair* in_regs, -- BasicType ret_type) { -+ BasicType ret_type, -+ address critical_entry) { - if (method->is_method_handle_intrinsic()) { - vmIntrinsics::ID iid = method->intrinsic_id(); - intptr_t start = (intptr_t)__ pc(); -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index dd65f32277f..c0491d23fa6 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -147,6 +147,8 @@ void VM_Version::initialize() { - #ifdef COMPILER2 - c2_initialize(); - #endif // COMPILER2 -+ -+ UNSUPPORTED_OPTION(CriticalJNINatives); - } - - #ifdef COMPILER2 -diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java -index acb86812d25..2c866f26f08 100644 ---- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java -+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/argumentcorruption/CheckLongArgs.java -@@ -24,7 +24,7 @@ - - /* @test - * @bug 8167409 -- * @requires (os.arch != "aarch64") & (os.arch != "arm") -+ * @requires (os.arch != "aarch64") & (os.arch != "riscv64") & (os.arch != "arm") - * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.argumentcorruption.CheckLongArgs - */ - package compiler.runtime.criticalnatives.argumentcorruption; -diff --git a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java -index eab36f93113..1da369fde23 100644 ---- a/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java -+++ b/test/hotspot/jtreg/compiler/runtime/criticalnatives/lookup/LookUp.java -@@ -24,7 +24,7 @@ - - /* @test - * @bug 8167408 -- * @requires (os.arch != "aarch64") & (os.arch != "arm") -+ * @requires (os.arch != "aarch64") & (os.arch != "riscv64") & (os.arch != "arm") - * @run main/othervm/native -Xcomp -XX:+CriticalJNINatives compiler.runtime.criticalnatives.lookup.LookUp - */ - package compiler.runtime.criticalnatives.lookup; - -From 58ad930e78501c6fad024e7ef05066ec19eb6219 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 11 Apr 2023 11:45:04 +0800 -Subject: [PATCH 036/140] 8202976: Add C1 lea patching support for x86 (RISC-V - part) - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index dd657963438..46a20a64194 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -1818,6 +1818,7 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C - return; - } - -+ assert(patch_code == lir_patch_none, "Patch code not supported"); - LIR_Address* adr = addr->as_address_ptr(); - Register dst = dest->as_register_lo(); - - -From 2074b8ec0ea3562f3999b4f4010b3f5b57dbe502 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 11 Apr 2023 12:15:44 +0800 -Subject: [PATCH 037/140] Revert 8232365: Implementation for JEP 363: Remove - the Concurrent Mark Sweep (CMS) Garbage Collector - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 3 +++ - src/hotspot/cpu/riscv/riscv.ad | 27 +++++++++++++++++++++++++ - 2 files changed, 30 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index 845064d6cbc..50bbb6a77b8 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -63,6 +63,9 @@ define_pd_global(bool, RewriteFrequentPairs, true); - - define_pd_global(bool, PreserveFramePointer, false); - -+// GC Ergo Flags -+define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS young gen, per GC worker thread -+ - define_pd_global(uintx, TypeProfileLevel, 111); - - define_pd_global(bool, CompactStrings, true); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 29027d594a0..386ef731696 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -752,6 +752,9 @@ bool is_CAS(int opcode, bool maybe_volatile); - // predicate controlling translation of CompareAndSwapX - bool needs_acquiring_load_reserved(const Node *load); - -+// predicate controlling translation of StoreCM -+bool unnecessary_storestore(const Node *storecm); -+ - // predicate controlling addressing modes - bool size_fits_all_mem_uses(AddPNode* addp, int shift); - %} -@@ -874,6 +877,29 @@ bool needs_acquiring_load_reserved(const Node *n) - // so we can just return true here - return true; - } -+ -+// predicate controlling translation of StoreCM -+// -+// returns true if a StoreStore must precede the card write otherwise -+// false -+ -+bool unnecessary_storestore(const Node *storecm) -+{ -+ assert(storecm->Opcode() == Op_StoreCM, "expecting a StoreCM"); -+ -+ // we need to generate a dmb ishst between an object put and the -+ // associated card mark when we are using CMS without conditional -+ // card marking -+ -+ if (UseConcMarkSweepGC && !UseCondCardMark) { -+ return false; -+ } -+ -+ // a storestore is unnecesary in all other cases -+ -+ return true; -+} -+ - #define __ _masm. - - // advance declarations for helper functions to convert register -@@ -4566,6 +4592,7 @@ instruct loadConD0(fRegD dst, immD0 con) %{ - instruct storeimmCM0(immI0 zero, memory mem) - %{ - match(Set mem (StoreCM mem zero)); -+ predicate(unnecessary_storestore(n)); - - ins_cost(STORE_COST); - format %{ "storestore (elided)\n\t" - -From f838cf41b48c6bc17d052531ab5594de236b1302 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 11 Apr 2023 22:06:58 +0800 -Subject: [PATCH 038/140] Revert 8220051: Remove global safepoint code - ---- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 3 +- - .../cpu/riscv/macroAssembler_riscv.cpp | 26 ++++++++++- - .../cpu/riscv/macroAssembler_riscv.hpp | 3 +- - src/hotspot/cpu/riscv/riscv.ad | 43 +++++++++++++++++++ - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 4 +- - .../templateInterpreterGenerator_riscv.cpp | 2 +- - 6 files changed, 75 insertions(+), 6 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 48957803fdc..74dded77d19 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -515,7 +515,8 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, - - Label safepoint; - address* const safepoint_table = Interpreter::safept_table(state); -- bool needs_thread_local_poll = generate_poll && table != safepoint_table; -+ bool needs_thread_local_poll = generate_poll && -+ SafepointMechanism::uses_thread_local_poll() && table != safepoint_table; - - if (needs_thread_local_poll) { - NOT_PRODUCT(block_comment("Thread-local Safepoint poll")); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index cf01d7d74bb..73629e3dba3 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -264,6 +264,30 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, - } - } - -+// Just like safepoint_poll, but use an acquiring load for thread- -+// local polling. -+// -+// We need an acquire here to ensure that any subsequent load of the -+// global SafepointSynchronize::_state flag is ordered after this load -+// of the local Thread::_polling page. We don't want this poll to -+// return false (i.e. not safepointing) and a later poll of the global -+// SafepointSynchronize::_state spuriously to return true. -+// -+// This is to avoid a race when we're in a native->Java transition -+// racing the code which wakes up from a safepoint. -+// -+void MacroAssembler::safepoint_poll_acquire(Label& slow_path) { -+ if (SafepointMechanism::uses_thread_local_poll()) { -+ membar(MacroAssembler::AnyAny); -+ ld(t1, Address(xthread, Thread::polling_page_offset())); -+ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); -+ andi(t0, t1, SafepointMechanism::poll_bit()); -+ bnez(t0, slow_path); -+ } else { -+ safepoint_poll(slow_path); -+ } -+} -+ - void MacroAssembler::reset_last_Java_frame(bool clear_fp) { - // we must set sp to zero to clear frame - sd(zr, Address(xthread, JavaThread::last_Java_sp_offset())); -@@ -2137,7 +2161,7 @@ void MacroAssembler::check_klass_subtype(Register sub_klass, - bind(L_failure); - } - --void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod) { -+void MacroAssembler::safepoint_poll(Label& slow_path) { - if (SafepointMechanism::uses_thread_local_poll()) { - ld(t1, Address(xthread, Thread::polling_page_offset())); - andi(t0, t1, SafepointMechanism::poll_bit()); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index f23f7e7d1e6..8a2c6e07d88 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -44,7 +44,8 @@ class MacroAssembler: public Assembler { - } - virtual ~MacroAssembler() {} - -- void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod); -+ void safepoint_poll(Label& slow_path); -+ void safepoint_poll_acquire(Label& slow_path); - - // Place a fence.i after code may have been modified due to a safepoint. - void safepoint_ifence(); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 386ef731696..2dde4453dac 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1213,6 +1213,14 @@ const Pipeline * MachEpilogNode::pipeline() const { - return MachNode::pipeline_class(); - } - -+// This method seems to be obsolete. It is declared in machnode.hpp -+// and defined in all *.ad files, but it is never called. Should we -+// get rid of it? -+int MachEpilogNode::safepoint_offset() const { -+ assert(do_polling(), "no return for this epilog node"); -+ return 4; -+} -+ - //============================================================================= - - // Figure out which register class each belongs in: rc_int, rc_float or -@@ -1907,6 +1915,17 @@ encode %{ - __ li(dst_reg, 1); - %} - -+ enc_class riscv_enc_mov_poll_page(iRegP dst, immPollPage src) %{ -+ MacroAssembler _masm(&cbuf); -+ int32_t offset = 0; -+ address page = (address)$src$$constant; -+ unsigned long align = (unsigned long)page & 0xfff; -+ assert(align == 0, "polling page must be page aligned"); -+ Register dst_reg = as_Register($dst$$reg); -+ __ la_patchable(dst_reg, Address(page, relocInfo::poll_type), offset); -+ __ addi(dst_reg, dst_reg, offset); -+ %} -+ - enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ - C2_MacroAssembler _masm(&cbuf); - __ load_byte_map_base($dst$$Register); -@@ -2688,6 +2707,17 @@ operand immP_1() - interface(CONST_INTER); - %} - -+// Polling Page Pointer Immediate -+operand immPollPage() -+%{ -+ predicate((address)n->get_ptr() == os::get_polling_page()); -+ match(ConP); -+ -+ op_cost(0); -+ format %{ %} -+ interface(CONST_INTER); -+%} -+ - // Card Table Byte Map Base - operand immByteMapBase() - %{ -@@ -4476,6 +4506,19 @@ instruct loadConP1(iRegPNoSp dst, immP_1 con) - ins_pipe(ialu_imm); - %} - -+// Load Poll Page Constant -+instruct loadConPollPage(iRegPNoSp dst, immPollPage con) -+%{ -+ match(Set dst con); -+ -+ ins_cost(ALU_COST * 6); -+ format %{ "movptr $dst, $con\t# Poll Page Ptr, #@loadConPollPage" %} -+ -+ ins_encode(riscv_enc_mov_poll_page(dst, con)); -+ -+ ins_pipe(ialu_imm); -+%} -+ - // Load Byte Map Base Constant - instruct loadByteMapBase(iRegPNoSp dst, immByteMapBase con) - %{ -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index f8585afbdc2..c501c8f7bac 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1573,7 +1573,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. - -- __ safepoint_poll(safepoint_in_progress, true /* at_return */, true /* acquire */, false /* in_nmethod */); -+ __ safepoint_poll_acquire(safepoint_in_progress); - __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); - __ bnez(t0, safepoint_in_progress); - __ bind(safepoint_in_progress_done); -@@ -2439,7 +2439,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t - __ bind(noException); - - Label no_adjust, bail; -- if (!cause_return) { -+ if (SafepointMechanism::uses_thread_local_poll() && !cause_return) { - // If our stashed return pc was modified by the runtime we avoid touching it - __ ld(t0, Address(fp, frame::return_addr_offset * wordSize)); - __ bne(x18, t0, no_adjust); -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index 76ae6f89e27..2d4baab2ab7 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -1143,7 +1143,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { - // - // This is to avoid a race when we're in a native->Java transition - // racing the code which wakes up from a safepoint. -- __ safepoint_poll(L, true /* at_return */, true /* acquire */, false /* in_nmethod */); -+ __ safepoint_poll_acquire(L); - __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); - __ beqz(t1, Continue); - __ bind(L); - -From 13faeae35312c59a1366d4f9c84da7157f06efc7 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 11 Apr 2023 22:15:14 +0800 -Subject: [PATCH 039/140] Revert 8253180: ZGC: Implementation of JEP 376: ZGC: - Concurrent Thread-Stack Processing - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 8 ++------ - src/hotspot/cpu/riscv/frame_riscv.hpp | 3 --- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 1 - - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 8 -------- - .../cpu/riscv/templateInterpreterGenerator_riscv.cpp | 9 --------- - 5 files changed, 2 insertions(+), 27 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 8e4f20fe561..b056eb2488a 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -495,8 +495,8 @@ frame frame::sender_for_compiled_frame(RegisterMap* map) const { - } - - //------------------------------------------------------------------------------ --// frame::sender_raw --frame frame::sender_raw(RegisterMap* map) const { -+// frame::sender -+frame frame::sender(RegisterMap* map) const { - // Default is we done have to follow them. The sender_for_xxx will - // update it accordingly - assert(map != NULL, "map must be set"); -@@ -521,10 +521,6 @@ frame frame::sender_raw(RegisterMap* map) const { - return frame(sender_sp(), link(), sender_pc()); - } - --frame frame::sender(RegisterMap* map) const { -- return sender_raw(map); --} -- - bool frame::is_interpreted_frame_valid(JavaThread* thread) const { - assert(is_interpreted_frame(), "Not an interpreted frame"); - // These are reasonable sanity checks -diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp -index c06aaa9e391..3b88f6d5a1a 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.hpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.hpp -@@ -196,7 +196,4 @@ - - static jint interpreter_frame_expression_stack_direction() { return -1; } - -- // returns the sending frame, without applying any barriers -- frame sender_raw(RegisterMap* map) const; -- - #endif // CPU_RISCV_FRAME_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 74dded77d19..4e642af87c4 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -571,7 +571,6 @@ void InterpreterMacroAssembler::dispatch_via(TosState state, address* table) { - - // remove activation - // --// Apply stack watermark barrier. - // Unlock the receiver if this is a synchronized method. - // Unlock any Java monitors from syncronized blocks. - // Remove the activation from the stack. -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index c501c8f7bac..d740c99c979 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1565,14 +1565,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - - // check for safepoint operation in progress and/or pending suspend requests - { -- // We need an acquire here to ensure that any subsequent load of the -- // global SafepointSynchronize::_state flag is ordered after this load -- // of the thread-local polling word. We don't want this poll to -- // return false (i.e. not safepointing) and a later poll of the global -- // SafepointSynchronize::_state spuriously to return true. -- // This is to avoid a race when we're in a native->Java transition -- // racing the code which wakes up from a safepoint. -- - __ safepoint_poll_acquire(safepoint_in_progress); - __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); - __ bnez(t0, safepoint_in_progress); -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index 2d4baab2ab7..a07dea35b73 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -1134,15 +1134,6 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { - // check for safepoint operation in progress and/or pending suspend requests - { - Label L, Continue; -- -- // We need an acquire here to ensure that any subsequent load of the -- // global SafepointSynchronize::_state flag is ordered after this load -- // of the thread-local polling word. We don't want this poll to -- // return false (i.e. not safepointing) and a later poll of the global -- // SafepointSynchronize::_state spuriously to return true. -- // -- // This is to avoid a race when we're in a native->Java transition -- // racing the code which wakes up from a safepoint. - __ safepoint_poll_acquire(L); - __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); - __ beqz(t1, Continue); - -From 99ca43f1e7e74f161b40466f49fc61aa734d334d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 12 Apr 2023 12:35:33 +0800 -Subject: [PATCH 040/140] JDK-8243155: AArch64: Add support for SqrtVF - ---- - src/hotspot/cpu/riscv/riscv.ad | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 2dde4453dac..9da8a76c190 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -7206,7 +7206,7 @@ instruct absD_reg(fRegD dst, fRegD src) %{ - %} - - instruct sqrtF_reg(fRegF dst, fRegF src) %{ -- match(Set dst (ConvD2F (SqrtD (ConvF2D src)))); -+ match(Set dst (SqrtF src)); - - ins_cost(FSQRT_COST); - format %{ "fsqrt.s $dst, $src\t#@sqrtF_reg" %} - -From 4bbd814dfbc33d3f1277dbb64f19a18f9f8c1a81 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 12 Apr 2023 15:11:49 +0800 -Subject: [PATCH 041/140] Revert JDK-8267098: AArch64: C1 StubFrames end - confusingly - ---- - src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 52 ++++++++++----------- - 1 file changed, 24 insertions(+), 28 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -index f523c9ed50a..1f58bde4df5 100644 ---- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -@@ -167,19 +167,14 @@ int StubAssembler::call_RT(Register oop_result, Register metadata_result, addres - return call_RT(oop_result, metadata_result, entry, arg_num); - } - --enum return_state_t { -- does_not_return, requires_return --}; -- - // Implementation of StubFrame - - class StubFrame: public StackObj { - private: - StubAssembler* _sasm; -- bool _return_state; - - public: -- StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state=requires_return); -+ StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments); - void load_argument(int offset_in_words, Register reg); - - ~StubFrame(); -@@ -197,9 +192,8 @@ void StubAssembler::epilogue() { - - #define __ _sasm-> - --StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments, return_state_t return_state) { -+StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) { - _sasm = sasm; -- _return_state = return_state; - __ prologue(name, must_gc_arguments); - } - -@@ -211,11 +205,7 @@ void StubFrame::load_argument(int offset_in_words, Register reg) { - - - StubFrame::~StubFrame() { -- if (_return_state == requires_return) { -- __ epilogue(); -- } else { -- __ should_not_reach_here(); -- } -+ __ epilogue(); - _sasm = NULL; - } - -@@ -378,6 +368,7 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe - assert_cond(oop_maps != NULL); - oop_maps->add_gc_map(call_offset, oop_map); - -+ __ should_not_reach_here(); - return oop_maps; - } - -@@ -425,7 +416,9 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { - sasm->set_frame_size(frame_size); - break; - } -- default: ShouldNotReachHere(); -+ default: -+ __ should_not_reach_here(); -+ break; - } - - // verify that only x10 and x13 are valid at this time -@@ -481,6 +474,9 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { - restore_live_registers(sasm, id != handle_exception_nofpu_id); - break; - case handle_exception_from_callee_id: -+ // Pop the return address. -+ __ leave(); -+ __ ret(); // jump to exception handler - break; - default: ShouldNotReachHere(); - } -@@ -641,13 +637,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case throw_div0_exception_id: - { -- StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "throw_div0_exception", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); - } - break; - - case throw_null_pointer_exception_id: -- { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments, does_not_return); -+ { StubFrame f(sasm, "throw_null_pointer_exception", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); - } - break; -@@ -926,14 +922,14 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case throw_class_cast_exception_id: - { -- StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "throw_class_cast_exception", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); - } - break; - - case throw_incompatible_class_change_error_id: - { -- StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "throw_incompatible_class_cast_exception", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, - CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); - } -@@ -1027,7 +1023,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case deoptimize_id: - { -- StubFrame f(sasm, "deoptimize", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "deoptimize", dont_gc_arguments); - OopMap* oop_map = save_live_registers(sasm); - assert_cond(oop_map != NULL); - f.load_argument(0, c_rarg1); -@@ -1046,7 +1042,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case throw_range_check_failed_id: - { -- StubFrame f(sasm, "range_check_failed", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "range_check_failed", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); - } - break; -@@ -1062,7 +1058,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case access_field_patching_id: - { -- StubFrame f(sasm, "access_field_patching", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "access_field_patching", dont_gc_arguments); - // we should set up register map - oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); - } -@@ -1070,7 +1066,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case load_klass_patching_id: - { -- StubFrame f(sasm, "load_klass_patching", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "load_klass_patching", dont_gc_arguments); - // we should set up register map - oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); - } -@@ -1078,7 +1074,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case load_mirror_patching_id: - { -- StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "load_mirror_patching", dont_gc_arguments); - // we should set up register map - oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); - } -@@ -1086,7 +1082,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case load_appendix_patching_id: - { -- StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments); - // we should set up register map - oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); - } -@@ -1109,14 +1105,14 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case throw_index_exception_id: - { -- StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "index_range_check_failed", dont_gc_arguments); - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); - } - break; - - case throw_array_store_exception_id: - { -- StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "throw_array_store_exception", dont_gc_arguments); - // tos + 0: link - // + 1: return address - oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); -@@ -1125,7 +1121,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - case predicate_failed_trap_id: - { -- StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments); - - OopMap* map = save_live_registers(sasm); - assert_cond(map != NULL); -@@ -1156,7 +1152,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - - default: - { -- StubFrame f(sasm, "unimplemented entry", dont_gc_arguments, does_not_return); -+ StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); - __ li(x10, (int) id); - __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), x10); - __ should_not_reach_here(); - -From eb37cfd42e7801c5ce64666c3cd25d40cfb22e76 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 12 Apr 2023 18:06:40 +0800 -Subject: [PATCH 042/140] Revert JDK-8247691: [aarch64] Incorrect handling of - VM exceptions in C1 deopt stub/traps - ---- - src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 87 +++++++++++++++------ - 1 file changed, 65 insertions(+), 22 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -index 1f58bde4df5..1f45fba9de0 100644 ---- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -@@ -581,37 +581,80 @@ OopMapSet* Runtime1::generate_patching(StubAssembler* sasm, address target) { - #endif - __ reset_last_Java_frame(true); - --#ifdef ASSERT -- // Check that fields in JavaThread for exception oop and issuing pc are empty -- Label oop_empty; -- __ ld(t0, Address(xthread, Thread::pending_exception_offset())); -- __ beqz(t0, oop_empty); -- __ stop("exception oop must be empty"); -- __ bind(oop_empty); -+ // check for pending exceptions -+ { Label L; -+ __ ld(t0, Address(xthread, Thread::pending_exception_offset())); -+ __ beqz(t0, L); -+ // exception pending => remove activation and forward to exception handler - -- Label pc_empty; -- __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); -- __ beqz(t0, pc_empty); -- __ stop("exception pc must be empty"); -- __ bind(pc_empty); -+ { Label L1; -+ __ bnez(x10, L1); // have we deoptimized? -+ __ far_jump(RuntimeAddress(Runtime1::entry_for(Runtime1::forward_exception_id))); -+ __ bind(L1); -+ } -+ -+ // the deopt blob expects exceptions in the special fields of -+ // JavaThread, so copy and clear pending exception. -+ -+ // load and clear pending exception -+ __ ld(x10, Address(xthread, Thread::pending_exception_offset())); -+ __ sd(zr, Address(xthread, Thread::pending_exception_offset())); -+ -+ // check that there is really a valid exception -+ __ verify_not_null_oop(x10); -+ -+ // load throwing pc: this is the return address of the stub -+ __ ld(x13, Address(fp, wordSize)); -+ -+#ifdef ASSERT -+ // Check that fields in JavaThread for exception oop and issuing pc are empty -+ Label oop_empty; -+ __ ld(t0, Address(xthread, Thread::pending_exception_offset())); -+ __ beqz(t0, oop_empty); -+ __ stop("exception oop must be empty"); -+ __ bind(oop_empty); -+ -+ Label pc_empty; -+ __ ld(t0, Address(xthread, JavaThread::exception_pc_offset())); -+ __ beqz(t0, pc_empty); -+ __ stop("exception pc must be empty"); -+ __ bind(pc_empty); - #endif - -- // Runtime will return true if the nmethod has been deoptimized, this is the -- // expected scenario and anything else is an error. Note that we maintain a -- // check on the result purely as a defensive measure. -- Label no_deopt; -- __ beqz(x10, no_deopt); // Have we deoptimized? -+ // store exception oop and throwing pc to JavaThread -+ __ sd(x10, Address(xthread, JavaThread::exception_oop_offset())); -+ __ sd(x13, Address(xthread, JavaThread::exception_pc_offset())); -+ -+ restore_live_registers(sasm); - -- // Perform a re-execute. The proper return address is already on the stack, -- // we just need to restore registers, pop all of our frames but the return -- // address and jump to the deopt blob. -+ __ leave(); -+ -+ // Forward the exception directly to deopt blob. We can blow no -+ // registers and must leave throwing pc on the stack. A patch may -+ // have values live in registers so the entry point with the -+ // exception in tls. -+ __ far_jump(RuntimeAddress(deopt_blob->unpack_with_exception_in_tls())); -+ -+ __ bind(L); -+ } -+ -+ // Runtime will return true if the nmethod has been deoptimized during -+ // the patching process. In that case we must do a deopt reexecute instead. -+ Label cont; -+ -+ __ beqz(x10, cont); // have we deoptimized? -+ -+ // Will reexecute. Proper return address is already on the stack we just restore -+ // registers, pop all of our frame but the return address and jump to the deopt blob - - restore_live_registers(sasm); - __ leave(); - __ far_jump(RuntimeAddress(deopt_blob->unpack_with_reexecution())); - -- __ bind(no_deopt); -- __ stop("deopt not performed"); -+ __ bind(cont); -+ restore_live_registers(sasm); -+ __ leave(); -+ __ ret(); - - return oop_maps; - } - -From 3fa279b459fffd1bd1ce158a7fdaa9d8704450a8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 13 Apr 2023 18:29:27 +0800 -Subject: [PATCH 043/140] Revert JDK-8212681: Refactor IC locking to use a fine - grained CompiledICLocker - ---- - src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 3 +-- - 2 files changed, 2 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -index 75bc4be7840..4d1687301fc 100644 ---- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -@@ -113,10 +113,10 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad - } - - void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_stub) { -+ assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call"); - // Reset stub. - address stub = static_stub->addr(); - assert(stub != NULL, "stub not found"); -- assert(CompiledICLocker::is_safe(stub), "mt unsafe call"); - // Creation also verifies the object. - NativeMovConstReg* method_holder - = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); -diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -index 0a05c577860..459683735e9 100644 ---- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -@@ -146,8 +146,7 @@ address NativeCall::destination() const { - // during code generation, where no patching lock is needed. - void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { - assert(!assert_lock || -- (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()) || -- CompiledICLocker::is_safe(addr_at(0)), -+ (Patching_lock->is_locked() || SafepointSynchronize::is_at_safepoint()), - "concurrent code patching"); - - ResourceMark rm; - -From 727f1a8f9b4a6dfbb0cf2002f12b86b5d5f23362 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 13 Apr 2023 18:36:11 +0800 -Subject: [PATCH 044/140] Revert JDK-8225681: - vmTestbase/nsk/jvmti/RedefineClasses/StressRedefine fails due a) MT-unsafe - modification of inline cache - ---- - src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -index 4d1687301fc..0b13e44c8d6 100644 ---- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -@@ -99,10 +99,15 @@ void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, ad - // Creation also verifies the object. - NativeMovConstReg* method_holder - = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); --#ifdef ASSERT -+#ifndef PRODUCT - NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); - -- verify_mt_safe(callee, entry, method_holder, jump); -+ // read the value once -+ volatile intptr_t data = method_holder->data(); -+ assert(data == 0 || data == (intptr_t)callee(), -+ "a) MT-unsafe modification of inline cache"); -+ assert(data == 0 || jump->jump_destination() == entry, -+ "b) MT-unsafe modification of inline cache"); - #endif - // Update stub. - method_holder->set_data((intptr_t)callee()); - -From 26e37551ecc41db0cf8eeb775a5501b4f45b4ffa Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 13 Apr 2023 18:39:52 +0800 -Subject: [PATCH 045/140] Revert JDK-8232046: AArch64 build failure after - JDK-8225681 - ---- - src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 2 -- - src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 19 ++++--------------- - 2 files changed, 4 insertions(+), 17 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -index 0b13e44c8d6..1cfc92b28fa 100644 ---- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -@@ -126,8 +126,6 @@ void CompiledDirectStaticCall::set_stub_to_clean(static_stub_Relocation* static_ - NativeMovConstReg* method_holder - = nativeMovConstReg_at(stub + NativeFenceI::instruction_size()); - method_holder->set_data(0); -- NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); -- jump->set_jump_destination((address)-1); - } - - //----------------------------------------------------------------------------- -diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -index 459683735e9..bfe84fa4e30 100644 ---- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -@@ -272,15 +272,9 @@ address NativeJump::jump_destination() const { - - // We use jump to self as the unresolved address which the inline - // cache code (and relocs) know about -- // As a special case we also use sequence movptr_with_offset(r,0), jalr(r,0) -- // i.e. jump to 0 when we need leave space for a wide immediate -- // load -- -- // return -1 if jump to self or to 0 -- if ((dest == (address) this) || dest == 0) { -- dest = (address) -1; -- } - -+ // return -1 if jump to self -+ dest = (dest == (address) this) ? (address) -1 : dest; - return dest; - }; - -@@ -302,14 +296,9 @@ address NativeGeneralJump::jump_destination() const { - - // We use jump to self as the unresolved address which the inline - // cache code (and relocs) know about -- // As a special case we also use jump to 0 when first generating -- // a general jump -- -- // return -1 if jump to self or to 0 -- if ((dest == (address) this) || dest == 0) { -- dest = (address) -1; -- } - -+ // return -1 if jump to self -+ dest = (dest == (address) this) ? (address) -1 : dest; - return dest; - } - - -From 4fc68bc3cd13e623276965947d6c8cb14da15873 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 13 Apr 2023 18:47:08 +0800 -Subject: [PATCH 046/140] Revert JDK-8213084: Rework and enhance - Print[Opto]Assembly output - ---- - src/hotspot/cpu/riscv/assembler_riscv.hpp | 8 -------- - src/hotspot/cpu/riscv/disassembler_riscv.hpp | 20 -------------------- - 2 files changed, 28 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp -index 44e8d4b4ff1..b4e7287ce08 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -268,14 +268,6 @@ class Assembler : public AbstractAssembler { - - enum { instruction_size = 4 }; - -- //---< calculate length of instruction >--- -- // We just use the values set above. -- // instruction must start at passed address -- static unsigned int instr_len(unsigned char *instr) { return instruction_size; } -- -- //---< longest instructions >--- -- static unsigned int instr_maxlen() { return instruction_size; } -- - enum RoundingMode { - rne = 0b000, // round to Nearest, ties to Even - rtz = 0b001, // round towards Zero -diff --git a/src/hotspot/cpu/riscv/disassembler_riscv.hpp b/src/hotspot/cpu/riscv/disassembler_riscv.hpp -index b0e5560c906..06bca5298cd 100644 ---- a/src/hotspot/cpu/riscv/disassembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/disassembler_riscv.hpp -@@ -35,24 +35,4 @@ static const char* pd_cpu_opts() { - return ""; - } - --// Returns address of n-th instruction preceding addr, --// NULL if no preceding instruction can be found. --// On riscv, we assume a constant instruction length. --// It might be beneficial to check "is_readable" as we do on ppc and s390. --static address find_prev_instr(address addr, int n_instr) { -- return addr - Assembler::instruction_size * n_instr; --} -- --// special-case instruction decoding. --// There may be cases where the binutils disassembler doesn't do --// the perfect job. In those cases, decode_instruction0 may kick in --// and do it right. --// If nothing had to be done, just return "here", otherwise return "here + instr_len(here)" --static address decode_instruction0(address here, outputStream* st, address virtual_begin = NULL) { -- return here; --} -- --// platform-specific instruction annotations (like value of loaded constants) --static void annotate(address pc, outputStream* st) {} -- - #endif // CPU_RISCV_DISASSEMBLER_RISCV_HPP - -From f660c594eccb174c9779ebdc9ba40fe579aa50cc Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 13 Apr 2023 19:44:28 +0800 -Subject: [PATCH 047/140] Revert JDK-8241909: Remove useless code cache lookup - in frame::patch_pc - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index b056eb2488a..d03adc0bff4 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -270,7 +270,6 @@ bool frame::safe_for_sender(JavaThread *thread) { - } - - void frame::patch_pc(Thread* thread, address pc) { -- assert(_cb == CodeCache::find_blob(pc), "unexpected pc"); - address* pc_addr = &(((address*) sp())[-1]); - if (TracePcPatching) { - tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]", -@@ -280,6 +279,7 @@ void frame::patch_pc(Thread* thread, address pc) { - // patch in the same address that's already there. - assert(_pc == *pc_addr || pc == *pc_addr, "must be"); - *pc_addr = pc; -+ _cb = CodeCache::find_blob(pc); - address original_pc = CompiledMethod::get_deopt_original_pc(this); - if (original_pc != NULL) { - assert(original_pc == _pc, "expected original PC to be stored before patching"); - -From 0d1ed436d9b70c9244c5de42fb492bbfa5e785e8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 16 Apr 2023 21:10:06 +0800 -Subject: [PATCH 048/140] Revert JDK-8277411: C2 fast_unlock intrinsic on - AArch64 has unnecessary ownership check & JDK-8277180: Intrinsify recursive - ObjectMonitor locking for C2 x64 and A64 - ---- - src/hotspot/cpu/riscv/riscv.ad | 24 ++++-------------------- - 1 file changed, 4 insertions(+), 20 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 9da8a76c190..c0fbda4f3f9 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2204,16 +2204,6 @@ encode %{ - __ mv(tmp, (address)markOopDesc::unused_mark()); - __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); - -- __ beqz(flag, cont); // CAS success means locking succeeded -- -- __ bne(flag, xthread, cont); // Check for recursive locking -- -- // Recursive lock case -- __ mv(flag, zr); -- __ ld(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markOopDesc::monitor_value)); -- __ add(tmp, tmp, 1u); -- __ sd(tmp, Address(disp_hdr, ObjectMonitor::recursions_offset_in_bytes() - markOopDesc::monitor_value)); -- - __ bind(cont); - %} - -@@ -2257,18 +2247,12 @@ encode %{ - __ bind(object_has_monitor); - STATIC_ASSERT(markOopDesc::monitor_value <= INT_MAX); - __ add(tmp, tmp, -(int)markOopDesc::monitor_value); // monitor -+ __ ld(flag, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); - __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); -+ __ xorr(flag, flag, xthread); // Will be 0 if we are the owner. -+ __ orr(flag, flag, disp_hdr); // Will be 0 if there are 0 recursions -+ __ bnez(flag, cont); - -- Label notRecursive; -- __ beqz(disp_hdr, notRecursive); // Will be 0 if not recursive. -- -- // Recursive lock -- __ addi(disp_hdr, disp_hdr, -1); -- __ sd(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); -- __ mv(flag, zr); -- __ j(cont); -- -- __ bind(notRecursive); - __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); - __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); - __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. - -From cac7117dfc03023a81030e274944921df07bbead Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 16 Apr 2023 21:13:21 +0800 -Subject: [PATCH 049/140] Revert JDK-8210381: Obsolete EmitSync - ---- - src/hotspot/cpu/riscv/riscv.ad | 100 ++++++++++++++++++++------------- - 1 file changed, 60 insertions(+), 40 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c0fbda4f3f9..c3ef648b21d 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2150,9 +2150,17 @@ encode %{ - // Load markWord from object into displaced_header. - __ ld(disp_hdr, Address(oop, oopDesc::mark_offset_in_bytes())); - -+ // Always do locking in runtime. -+ if (EmitSync & 0x01) { -+ __ mv(flag, 1); -+ return; -+ } -+ - // Check for existing monitor -- __ andi(t0, disp_hdr, markOopDesc::monitor_value); -- __ bnez(t0, object_has_monitor); -+ if ((EmitSync & 0x02) == 0) { -+ __ andi(t0, disp_hdr, markOopDesc::monitor_value); -+ __ bnez(t0, object_has_monitor); -+ } - - // Set tmp to be (markWord of object | UNLOCK_VALUE). - __ ori(tmp, disp_hdr, markOopDesc::unlocked_value); -@@ -2185,24 +2193,26 @@ encode %{ - __ sd(tmp/*==0, perhaps*/, Address(box, BasicLock::displaced_header_offset_in_bytes())); - __ mv(flag, tmp); // we can use the value of tmp as the result here - -- __ j(cont); -- -- // Handle existing monitor. -- __ bind(object_has_monitor); -- // The object's monitor m is unlocked iff m->owner == NULL, -- // otherwise m->owner may contain a thread or a stack address. -- // -- // Try to CAS m->owner from NULL to current thread. -- __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value)); -- __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, -- Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) -- -- // Store a non-null value into the box to avoid looking like a re-entrant -- // lock. The fast-path monitor unlock code checks for -- // markOopDesc::monitor_value so use markOopDesc::unused_mark which has the -- // relevant bit set, and also matches ObjectSynchronizer::slow_enter. -- __ mv(tmp, (address)markOopDesc::unused_mark()); -- __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ if ((EmitSync & 0x02) == 0) { -+ __ j(cont); -+ -+ // Handle existing monitor. -+ __ bind(object_has_monitor); -+ // The object's monitor m is unlocked iff m->owner == NULL, -+ // otherwise m->owner may contain a thread or a stack address. -+ // -+ // Try to CAS m->owner from NULL to current thread. -+ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes() - markOopDesc::monitor_value)); -+ __ cmpxchg(/*memory address*/tmp, /*expected value*/zr, /*new value*/xthread, Assembler::int64, Assembler::aq, -+ Assembler::rl, /*result*/flag); // cas succeeds if flag == zr(expected) -+ -+ // Store a non-null value into the box to avoid looking like a re-entrant -+ // lock. The fast-path monitor unlock code checks for -+ // markOopDesc::monitor_value so use markOopDesc::unused_mark which has the -+ // relevant bit set, and also matches ObjectSynchronizer::slow_enter. -+ __ mv(tmp, (address)markOopDesc::unused_mark()); -+ __ sd(tmp, Address(box, BasicLock::displaced_header_offset_in_bytes())); -+ } - - __ bind(cont); - %} -@@ -2220,6 +2230,12 @@ encode %{ - - assert_different_registers(oop, box, tmp, disp_hdr, flag); - -+ // Always do locking in runtime. -+ if (EmitSync & 0x01) { -+ __ mv(flag, 1); -+ return; -+ } -+ - // Find the lock address and load the displaced header from the stack. - __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); - -@@ -2228,9 +2244,11 @@ encode %{ - __ beqz(disp_hdr, cont); - - // Handle existing monitor. -- __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); -- __ andi(t0, disp_hdr, markOopDesc::monitor_value); -- __ bnez(t0, object_has_monitor); -+ if ((EmitSync & 0x02) == 0) { -+ __ ld(tmp, Address(oop, oopDesc::mark_offset_in_bytes())); -+ __ andi(t0, disp_hdr, markOopDesc::monitor_value); -+ __ bnez(t0, object_has_monitor); -+ } - - // Check if it is still a light weight lock, this is true if we - // see the stack address of the basicLock in the markWord of the -@@ -2244,23 +2262,25 @@ encode %{ - assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); - - // Handle existing monitor. -- __ bind(object_has_monitor); -- STATIC_ASSERT(markOopDesc::monitor_value <= INT_MAX); -- __ add(tmp, tmp, -(int)markOopDesc::monitor_value); // monitor -- __ ld(flag, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); -- __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); -- __ xorr(flag, flag, xthread); // Will be 0 if we are the owner. -- __ orr(flag, flag, disp_hdr); // Will be 0 if there are 0 recursions -- __ bnez(flag, cont); -- -- __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); -- __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); -- __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. -- __ bnez(flag, cont); -- // need a release store here -- __ la(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); -- __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); -- __ sd(zr, Address(tmp)); // set unowned -+ if ((EmitSync & 0x02) == 0) { -+ __ bind(object_has_monitor); -+ STATIC_ASSERT(markOopDesc::monitor_value <= INT_MAX); -+ __ add(tmp, tmp, -(int)markOopDesc::monitor_value); // monitor -+ __ ld(flag, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); -+ __ ld(disp_hdr, Address(tmp, ObjectMonitor::recursions_offset_in_bytes())); -+ __ xorr(flag, flag, xthread); // Will be 0 if we are the owner. -+ __ orr(flag, flag, disp_hdr); // Will be 0 if there are 0 recursions -+ __ bnez(flag, cont); -+ -+ __ ld(flag, Address(tmp, ObjectMonitor::EntryList_offset_in_bytes())); -+ __ ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset_in_bytes())); -+ __ orr(flag, flag, disp_hdr); // Will be 0 if both are 0. -+ __ bnez(flag, cont); -+ // need a release store here -+ __ la(tmp, Address(tmp, ObjectMonitor::owner_offset_in_bytes())); -+ __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); -+ __ sd(zr, Address(tmp)); // set unowned -+ } - - __ bind(cont); - %} - -From ca7ab86ee886233651e1a79faff631fd7e226d57 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 16 Apr 2023 22:07:21 +0800 -Subject: [PATCH 050/140] Revert JDK-8256425: Obsolete Biased Locking in JDK 18 - ---- - src/hotspot/cpu/riscv/assembler_riscv.hpp | 2 + - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 6 +- - .../cpu/riscv/c1_LIRGenerator_riscv.cpp | 7 +- - .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 35 ++- - .../cpu/riscv/c1_MacroAssembler_riscv.hpp | 3 +- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 27 ++- - .../cpu/riscv/macroAssembler_riscv.cpp | 217 ++++++++++++++++++ - .../cpu/riscv/macroAssembler_riscv.hpp | 28 +++ - src/hotspot/cpu/riscv/riscv.ad | 12 + - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 8 + - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 8 +- - 11 files changed, 341 insertions(+), 12 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp -index b4e7287ce08..51aa052a0c7 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -3043,4 +3043,6 @@ enum Nf { - virtual ~Assembler() {} - }; - -+class BiasedLockingCounters; -+ - #endif // CPU_RISCV_ASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 46a20a64194..6a961ee2307 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -1511,9 +1511,13 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { - if (!UseFastLocking) { - __ j(*op->stub()->entry()); - } else if (op->code() == lir_lock) { -+ Register scratch = noreg; -+ if (UseBiasedLocking) { -+ scratch = op->scratch_opr()->as_register(); -+ } - assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header"); - // add debug info for NullPointerException only if one is possible -- int null_check_offset = __ lock_object(hdr, obj, lock, *op->stub()->entry()); -+ int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry()); - if (op->info() != NULL) { - add_debug_info_for_null_check(null_check_offset, op->info()); - } -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index e126f148cdf..c45a75b2301 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -277,6 +277,11 @@ void LIRGenerator::do_MonitorEnter(MonitorEnter* x) { - - // "lock" stores the address of the monitor stack slot, so this is not an oop - LIR_Opr lock = new_register(T_INT); -+ // Need a scratch register for biased locking -+ LIR_Opr scratch = LIR_OprFact::illegalOpr; -+ if (UseBiasedLocking) { -+ scratch = new_register(T_INT); -+ } - - CodeEmitInfo* info_for_exception = NULL; - if (x->needs_null_check()) { -@@ -285,7 +290,7 @@ void LIRGenerator::do_MonitorEnter(MonitorEnter* x) { - // this CodeEmitInfo must not have the xhandlers because here the - // object is already locked (xhandlers expect object to be unlocked) - CodeEmitInfo* info = state_for(x, x->state(), true); -- monitor_enter(obj.result(), lock, syncTempOpr(), LIR_OprFact::illegalOpr, -+ monitor_enter(obj.result(), lock, syncTempOpr(), scratch, - x->monitor_no(), info_for_exception, info); - } - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index 2d52343587e..e486f41948e 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -35,6 +35,7 @@ - #include "oops/arrayOop.hpp" - #include "oops/markWord.hpp" - #include "runtime/basicLock.hpp" -+#include "runtime/biasedLocking.hpp" - #include "runtime/os.hpp" - #include "runtime/sharedRuntime.hpp" - #include "runtime/stubRoutines.hpp" -@@ -50,7 +51,7 @@ void C1_MacroAssembler::float_cmp(bool is_float, int unordered_result, - } - } - --int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) { -+int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register scratch, Label& slow_case) { - const int aligned_mask = BytesPerWord - 1; - const int hdr_offset = oopDesc::mark_offset_in_bytes(); - assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); -@@ -62,7 +63,12 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr - // save object being locked into the BasicObjectLock - sd(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); - -- null_check_offset = offset(); -+ if (UseBiasedLocking) { -+ assert(scratch != noreg, "should have scratch register at this point"); -+ null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case); -+ } else { -+ null_check_offset = offset(); -+ } - - // Load object header - ld(hdr, Address(obj, hdr_offset)); -@@ -98,6 +104,10 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr - // otherwise we don't care about the result and handle locking via runtime call - bnez(hdr, slow_case, /* is_far */ true); - bind(done); -+ if (PrintBiasedLockingStatistics) { -+ la(t1, ExternalAddress((address)BiasedLocking::fast_path_entry_count_addr())); -+ add_memory_int32(Address(t1, 0), 1); -+ } - return null_check_offset; - } - -@@ -107,13 +117,21 @@ void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_ - assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different"); - Label done; - -+ if (UseBiasedLocking) { -+ // load object -+ ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); -+ biased_locking_exit(obj, hdr, done); -+ } -+ - // load displaced header - ld(hdr, Address(disp_hdr, 0)); - // if the loaded hdr is NULL we had recursive locking - // if we had recursive locking, we are done - beqz(hdr, done); -- // load object -- ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); -+ if (!UseBiasedLocking) { -+ // load object -+ ld(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); -+ } - verify_oop(obj); - // 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 -@@ -140,8 +158,13 @@ void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, i - - void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register tmp1, Register tmp2) { - assert_different_registers(obj, klass, len); -- // This assumes that all prototype bits fitr in an int32_t -- mv(tmp1, (int32_t)(intptr_t)markOopDesc::prototype()); -+ if (UseBiasedLocking && !len->is_valid()) { -+ assert_different_registers(obj, klass, len, tmp1, tmp2); -+ ld(tmp1, Address(klass, Klass::prototype_header_offset())); -+ } else { -+ // This assumes that all prototype bits fitr in an int32_t -+ mv(tmp1, (int32_t)(intptr_t)markOopDesc::prototype()); -+ } - sd(tmp1, Address(obj, oopDesc::mark_offset_in_bytes())); - - if (UseCompressedClassPointers) { // Take care not to kill klass -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp -index dfd3c17d7c7..1950cee5dd5 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.hpp -@@ -59,8 +59,9 @@ using MacroAssembler::null_check; - // hdr : must be x10, contents destroyed - // obj : must point to the object to lock, contents preserved - // disp_hdr: must point to the displaced header location, contents preserved -+ // scratch : scratch register, contents destroyed - // returns code offset at which to add null check debug information -- int lock_object (Register swap, Register obj, Register disp_hdr, Label& slow_case); -+ int lock_object (Register swap, Register obj, Register disp_hdr, Register scratch, Label& slow_case); - - // unlocking - // hdr : contents destroyed -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 4e642af87c4..f0c249f0d26 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -39,6 +39,7 @@ - #include "prims/jvmtiExport.hpp" - #include "prims/jvmtiThreadState.hpp" - #include "runtime/basicLock.hpp" -+#include "runtime/biasedLocking.hpp" - #include "runtime/frame.inline.hpp" - #include "runtime/safepointMechanism.hpp" - #include "runtime/sharedRuntime.hpp" -@@ -782,6 +783,10 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) - // Load object pointer into obj_reg c_rarg3 - ld(obj_reg, Address(lock_reg, obj_offset)); - -+ if (UseBiasedLocking) { -+ biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp, false, done, &slow_case); -+ } -+ - // Load (object->mark() | 1) into swap_reg - ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - ori(swap_reg, t0, 1); -@@ -792,7 +797,17 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) - assert(lock_offset == 0, - "displached header must be first word in BasicObjectLock"); - -- cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, done, /*fallthrough*/NULL); -+ if (PrintBiasedLockingStatistics) { -+ Label fail, fast; -+ cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, fast, &fail); -+ bind(fast); -+ atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), -+ t1, t0); -+ j(done); -+ bind(fail); -+ } else { -+ cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, t0, done, /*fallthrough*/NULL); -+ } - - // Test if the oopMark is an obvious stack pointer, i.e., - // 1) (mark & 7) == 0, and -@@ -809,6 +824,12 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) - - // Save the test result, for recursive case, the result is zero - sd(swap_reg, Address(lock_reg, mark_offset)); -+ -+ if (PrintBiasedLockingStatistics) { -+ bnez(swap_reg, slow_case); -+ atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), -+ t1, t0); -+ } - beqz(swap_reg, done); - - bind(slow_case); -@@ -861,6 +882,10 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) - // Free entry - sd(zr, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); - -+ if (UseBiasedLocking) { -+ biased_locking_exit(obj_reg, header_reg, done); -+ } -+ - // Load the old header from BasicLock structure - ld(header_reg, Address(swap_reg, - BasicLock::displaced_header_offset_in_bytes())); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 73629e3dba3..e557a134b5b 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -41,6 +41,7 @@ - #include "oops/compressedOops.inline.hpp" - #include "oops/klass.inline.hpp" - #include "oops/oop.hpp" -+#include "runtime/biasedLocking.hpp" - #include "runtime/interfaceSupport.inline.hpp" - #include "runtime/jniHandles.inline.hpp" - #include "runtime/sharedRuntime.hpp" -@@ -2791,6 +2792,222 @@ void MacroAssembler::reserved_stack_check() { - bind(no_reserved_zone_enabling); - } - -+void MacroAssembler::atomic_incw(Register counter_addr, Register tmp) { -+ Label retry_load; -+ bind(retry_load); -+ // flush and load exclusive from the memory location -+ lr_w(tmp, counter_addr); -+ addw(tmp, tmp, 1); -+ // if we store+flush with no intervening write tmp wil be zero -+ sc_w(tmp, tmp, counter_addr); -+ bnez(tmp, retry_load); -+} -+ -+void MacroAssembler::load_prototype_header(Register dst, Register src) { -+ load_klass(dst, src); -+ ld(dst, Address(dst, Klass::prototype_header_offset())); -+} -+ -+int MacroAssembler::biased_locking_enter(Register lock_reg, -+ Register obj_reg, -+ Register swap_reg, -+ Register tmp_reg, -+ bool swap_reg_contains_mark, -+ Label& done, -+ Label* slow_case, -+ BiasedLockingCounters* counters, -+ Register flag) { -+ assert(UseBiasedLocking, "why call this otherwise?"); -+ assert_different_registers(lock_reg, obj_reg, swap_reg); -+ -+ if (PrintBiasedLockingStatistics && counters == NULL) -+ counters = BiasedLocking::counters(); -+ -+ assert_different_registers(lock_reg, obj_reg, swap_reg, tmp_reg, t0); -+ assert(markOopDesc::age_shift == markOopDesc::lock_bits + markOopDesc::biased_lock_bits, "biased locking makes assumptions about bit layout"); -+ Address mark_addr (obj_reg, oopDesc::mark_offset_in_bytes()); -+ -+ // Biased locking -+ // See whether the lock is currently biased toward our thread and -+ // whether the epoch is still valid -+ // Note that the runtime guarantees sufficient alignment of JavaThread -+ // pointers to allow age to be placed into low bits -+ // First check to see whether biasing is even enabled for this object -+ Label cas_label; -+ int null_check_offset = -1; -+ if (!swap_reg_contains_mark) { -+ null_check_offset = offset(); -+ ld(swap_reg, mark_addr); -+ } -+ andi(tmp_reg, swap_reg, markOopDesc::biased_lock_mask_in_place); -+ li(t0, markOopDesc::biased_lock_pattern); -+ bne(t0, tmp_reg, cas_label); -+ // The bias pattern is present in the object's header. Need to check -+ // whether the bias owner and the epoch are both still current. -+ load_prototype_header(tmp_reg, obj_reg); -+ orr(tmp_reg, tmp_reg, xthread); -+ xorr(tmp_reg, swap_reg, tmp_reg); -+ andi(tmp_reg, tmp_reg, ~((int) markOopDesc::age_mask_in_place)); -+ if (flag->is_valid()) { -+ mv(flag, tmp_reg); -+ } -+ if (counters != NULL) { -+ Label around; -+ bnez(tmp_reg, around); -+ atomic_incw(Address((address)counters->biased_lock_entry_count_addr()), tmp_reg, t0); -+ j(done); -+ bind(around); -+ } else { -+ beqz(tmp_reg, done); -+ } -+ -+ Label try_revoke_bias; -+ Label try_rebias; -+ -+ // At this point we know that the header has the bias pattern and -+ // that we are not the bias owner in the current epoch. We need to -+ // figure out more details about the state of the header in order to -+ // know what operations can be legally performed on the object's -+ // header. -+ -+ // If the low three bits in the xor result aren't clear, that means -+ // the prototype header is no longer biased and we have to revoke -+ // the bias on this object. -+ andi(t0, tmp_reg, markOopDesc::biased_lock_mask_in_place); -+ bnez(t0, try_revoke_bias); -+ -+ // Biasing is still enabled for this data type. See whether the -+ // epoch of the current bias is still valid, meaning that the epoch -+ // bits of the mark word are equal to the epoch bits of the -+ // prototype header. (Note that the prototype header's epoch bits -+ // only change at a safepoint.) If not, attempt to rebias the object -+ // toward the current thread. Note that we must be absolutely sure -+ // that the current epoch is invalid in order to do this because -+ // otherwise the manipulations it performs on the mark word are -+ // illegal. -+ andi(t0, tmp_reg, markOopDesc::epoch_mask_in_place); -+ bnez(t0, try_rebias); -+ -+ // The epoch of the current bias is still valid but we know nothing -+ // about the owner; it might be set or it might be clear. Try to -+ // acquire the bias of the object using an atomic operation. If this -+ // fails we will go in to the runtime to revoke the object's bias. -+ // Note that we first construct the presumed unbiased header so we -+ // don't accidentally blow away another thread's valid bias. -+ { -+ Label cas_success; -+ Label counter; -+ mv(t0, markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); -+ andr(swap_reg, swap_reg, t0); -+ orr(tmp_reg, swap_reg, xthread); -+ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, slow_case); -+ // cas failed here if slow_cass == NULL -+ if (flag->is_valid()) { -+ mv(flag, 1); -+ j(counter); -+ } -+ // If the biasing toward our thread failed, this means that -+ // another thread succeeded in biasing it toward itself and we -+ // need to revoke that bias. The revocation will occur in the -+ // interpreter runtime in the slow case. -+ bind(cas_success); -+ if (flag->is_valid()) { -+ mv(flag, 0); -+ bind(counter); -+ } -+ if (counters != NULL) { -+ atomic_incw(Address((address)counters->anonymously_biased_lock_entry_count_addr()), -+ tmp_reg, t0); -+ } -+ } -+ j(done); -+ -+ bind(try_rebias); -+ // At this point we know the epoch has expired, meaning that the -+ // current "bias owner", if any, is actually invalid. Under these -+ // circumstances _only_, we are allowed to use the current header's -+ // value as the comparison value when doing the cas to acquire the -+ // bias in the current epoch. In other words, we allow transfer of -+ // the bias from one thread to another directly in this situation. -+ // -+ // FIXME: due to a lack of registers we currently blow away the age -+ // bits in this situation. Should attempt to preserve them. -+ { -+ Label cas_success; -+ Label counter; -+ load_prototype_header(tmp_reg, obj_reg); -+ orr(tmp_reg, xthread, tmp_reg); -+ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, slow_case); -+ // cas failed here if slow_cass == NULL -+ if (flag->is_valid()) { -+ mv(flag, 1); -+ j(counter); -+ } -+ -+ // If the biasing toward our thread failed, then another thread -+ // succeeded in biasing it toward itself and we need to revoke that -+ // bias. The revocation will occur in the runtime in the slow case. -+ bind(cas_success); -+ if (flag->is_valid()) { -+ mv(flag, 0); -+ bind(counter); -+ } -+ if (counters != NULL) { -+ atomic_incw(Address((address)counters->rebiased_lock_entry_count_addr()), -+ tmp_reg, t0); -+ } -+ } -+ j(done); -+ -+ bind(try_revoke_bias); -+ // The prototype mark in the klass doesn't have the bias bit set any -+ // more, indicating that objects of this data type are not supposed -+ // to be biased any more. We are going to try to reset the mark of -+ // this object to the prototype value and fall through to the -+ // CAS-based locking scheme. Note that if our CAS fails, it means -+ // that another thread raced us for the privilege of revoking the -+ // bias of this particular object, so it's okay to continue in the -+ // normal locking code. -+ // -+ // FIXME: due to a lack of registers we currently blow away the age -+ // bits in this situation. Should attempt to preserve them. -+ { -+ Label cas_success, nope; -+ load_prototype_header(tmp_reg, obj_reg); -+ cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, t0, cas_success, &nope); -+ bind(cas_success); -+ -+ // Fall through to the normal CAS-based lock, because no matter what -+ // the result of the above CAS, some thread must have succeeded in -+ // removing the bias bit from the object's header. -+ if (counters != NULL) { -+ atomic_incw(Address((address)counters->revoked_lock_entry_count_addr()), tmp_reg, -+ t0); -+ } -+ bind(nope); -+ } -+ -+ bind(cas_label); -+ -+ return null_check_offset; -+} -+ -+void MacroAssembler::biased_locking_exit(Register obj_reg, Register tmp_reg, Label& done, Register flag) { -+ assert(UseBiasedLocking, "why call this otherwise?"); -+ -+ // Check for biased locking unlock case, which is a no-op -+ // Note: we do not have to check the thread ID for two reasons. -+ // First, the interpreter checks for IllegalMonitorStateException at -+ // a higher level. Second, if the bias was revoked while we held the -+ // lock, the object could not be rebiased toward another thread, so -+ // the bias bit would be clear. -+ ld(tmp_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); -+ andi(tmp_reg, tmp_reg, markOopDesc::biased_lock_mask_in_place); -+ sub(tmp_reg, tmp_reg, markOopDesc::biased_lock_pattern); -+ if (flag->is_valid()) { mv(flag, tmp_reg); } -+ beqz(tmp_reg, done); -+} -+ - // Move the address of the polling page into dest. - void MacroAssembler::get_polling_page(Register dest, address page, int32_t &offset, relocInfo::relocType rtype) { - if (SafepointMechanism::uses_thread_local_poll()) { -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 8a2c6e07d88..c1ffa120774 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -47,6 +47,32 @@ class MacroAssembler: public Assembler { - void safepoint_poll(Label& slow_path); - void safepoint_poll_acquire(Label& slow_path); - -+ // Biased locking support -+ // lock_reg and obj_reg must be loaded up with the appropriate values. -+ // swap_reg is killed. -+ // tmp_reg must be supplied and must not be rscratch1 or rscratch2 -+ // Optional slow case is for implementations (interpreter and C1) which branch to -+ // slow case directly. Leaves condition codes set for C2's Fast_Lock node. -+ // Returns offset of first potentially-faulting instruction for null -+ // check info (currently consumed only by C1). If -+ // swap_reg_contains_mark is true then returns -1 as it is assumed -+ // the calling code has already passed any potential faults. -+ int biased_locking_enter(Register lock_reg, Register obj_reg, -+ Register swap_reg, Register tmp_reg, -+ bool swap_reg_contains_mark, -+ Label& done, Label* slow_case = NULL, -+ BiasedLockingCounters* counters = NULL, -+ Register flag = noreg); -+ void biased_locking_exit (Register obj_reg, Register temp_reg, Label& done, Register flag = noreg); -+ -+ // Helper functions for statistics gathering. -+ // Unconditional atomic increment. -+ void atomic_incw(Register counter_addr, Register tmp); -+ void atomic_incw(Address counter_addr, Register tmp1, Register tmp2) { -+ la(tmp1, counter_addr); -+ atomic_incw(tmp1, tmp2); -+ } -+ - // Place a fence.i after code may have been modified due to a safepoint. - void safepoint_ifence(); - -@@ -225,6 +251,8 @@ class MacroAssembler: public Assembler { - // stored using routines that take a jobject. - void store_heap_oop_null(Address dst); - -+ void load_prototype_header(Register dst, Register src); -+ - // This dummy is to prevent a call to store_heap_oop from - // converting a zero (linke NULL) into a Register by giving - // the compiler two choices it can't resolve -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c3ef648b21d..c2a0be140e9 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2156,6 +2156,10 @@ encode %{ - return; - } - -+ if (UseBiasedLocking && !UseOptoBiasInlining) { -+ __ biased_locking_enter(box, oop, disp_hdr, tmp, true, cont, /*slow_case*/NULL, NULL, flag); -+ } -+ - // Check for existing monitor - if ((EmitSync & 0x02) == 0) { - __ andi(t0, disp_hdr, markOopDesc::monitor_value); -@@ -2236,6 +2240,10 @@ encode %{ - return; - } - -+ if (UseBiasedLocking && !UseOptoBiasInlining) { -+ __ biased_locking_exit(oop, tmp, cont, flag); -+ } -+ - // Find the lock address and load the displaced header from the stack. - __ ld(disp_hdr, Address(box, BasicLock::displaced_header_offset_in_bytes())); - -@@ -4961,6 +4969,10 @@ instruct storePConditional(memory heap_top_ptr, iRegP oldval, iRegP newval, rFla - ins_pipe(pipe_serial); - %} - -+// storeLConditional is used by PhaseMacroExpand::expand_lock_node -+// when attempting to rebias a lock towards the current thread. We -+// must use the acquire form of cmpxchg in order to guarantee acquire -+// semantics in this case. - instruct storeLConditional(indirect mem, iRegLNoSp oldval, iRegLNoSp newval, rFlagsReg cr) - %{ - match(Set cr (StoreLConditional mem (Binary oldval newval))); -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index d740c99c979..eaefcc2b595 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1489,6 +1489,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - // Load the oop from the handle - __ ld(obj_reg, Address(oop_handle_reg, 0)); - -+ if (UseBiasedLocking) { -+ __ biased_locking_enter(lock_reg, obj_reg, swap_reg, tmp, false, lock_done, &slow_path_lock); -+ } -+ - // Load (object->mark() | 1) into swap_reg % x10 - __ ld(t0, Address(obj_reg, oopDesc::mark_offset_in_bytes())); - __ ori(swap_reg, t0, 1); -@@ -1597,6 +1601,10 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - - Label done; - -+ if (UseBiasedLocking) { -+ __ biased_locking_exit(obj_reg, old_hdr, done); -+ } -+ - // Simple recursive lock? - __ ld(t0, Address(sp, lock_slot_offset * VMRegImpl::stack_slot_size)); - __ beqz(t0, done); -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index c9d399ccdaf..1e23fb4dc09 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -3563,9 +3563,13 @@ void TemplateTable::_new() { - __ bnez(x13, loop); - } - -- // initialize object hader only. -+ // initialize object header only. - __ bind(initialize_header); -- __ mv(t0, (intptr_t)markOopDesc::prototype()); -+ if (UseBiasedLocking) { -+ __ ld(t0, Address(x14, Klass::prototype_header_offset())); -+ } else { -+ __ mv(t0, (intptr_t)markOopDesc::prototype()); -+ } - __ sd(t0, Address(x10, oopDesc::mark_offset_in_bytes())); - __ store_klass_gap(x10, zr); // zero klass gap for compressed oops - __ store_klass(x10, x14); // store klass last - -From 864e551505bb816f3dc8a3bd1b065328ba7b5d65 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Mon, 17 Apr 2023 19:52:44 +0800 -Subject: [PATCH 051/140] Revert JDK-8227680: FastJNIAccessors: Check for JVMTI - field access event requests at runtime - ---- - .../cpu/riscv/jniFastGetField_riscv.cpp | 32 ++++--------------- - 1 file changed, 6 insertions(+), 26 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp -index 814ed23e471..f6e7351c4fc 100644 ---- a/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp -+++ b/src/hotspot/cpu/riscv/jniFastGetField_riscv.cpp -@@ -83,28 +83,10 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { - // An even value means there are no ongoing safepoint operations - __ andi(t0, rcounter, 1); - __ bnez(t0, slow); -- -- if (JvmtiExport::can_post_field_access()) { -- // Using barrier to order wrt. JVMTI check and load of result. -- __ membar(MacroAssembler::LoadLoad); -- -- // Check to see if a field access watch has been set before we -- // take the fast path. -- int32_t offset2; -- __ la_patchable(result, -- ExternalAddress((address) JvmtiExport::get_field_access_count_addr()), -- offset2); -- __ lwu(result, Address(result, offset2)); -- __ bnez(result, slow); -- -- __ mv(robj, c_rarg1); -- } else { -- // Using address dependency to order wrt. load of result. -- __ xorr(robj, c_rarg1, rcounter); -- __ xorr(robj, robj, rcounter); // obj, since -- // robj ^ rcounter ^ rcounter == robj -- // robj is address dependent on rcounter. -- } -+ __ xorr(robj, c_rarg1, rcounter); -+ __ xorr(robj, robj, rcounter); // obj, since -+ // robj ^ rcounter ^ rcounter == robj -+ // robj is address dependent on rcounter. - - // Both robj and t0 are clobbered by try_resolve_jobject_in_native. - BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -@@ -137,10 +119,8 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { - default: ShouldNotReachHere(); - } - -- // Using acquire: Order JVMTI check and load of result wrt. succeeding check -- // (LoadStore for volatile field). -- __ membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); -- -+ __ xorr(rcounter_addr, rcounter_addr, result); -+ __ xorr(rcounter_addr, rcounter_addr, result); - __ lw(t0, safepoint_counter_addr); - __ bne(rcounter, t0, slow); - - -From b822b64cb6be38cb7806fda3d56675674557c163 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 18 Apr 2023 16:34:32 +0800 -Subject: [PATCH 052/140] Revert JDK-8249768: Move static oops and - NullPointerException oops from Universe into OopStorage - ---- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index 1e23fb4dc09..fbcdcf60d9c 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -411,7 +411,6 @@ void TemplateTable::fast_aldc(bool wide) - int32_t offset = 0; - __ movptr_with_offset(rarg, Universe::the_null_sentinel_addr(), offset); - __ ld(tmp, Address(rarg, offset)); -- __ resolve_oop_handle(tmp); - __ bne(result, tmp, notNull); - __ mv(result, zr); // NULL object reference - __ bind(notNull); - -From c82c482aa065ffd39eab6b87a0ad6c6cbca1e3af Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 18 Apr 2023 16:58:23 +0800 -Subject: [PATCH 053/140] Revert JDK-8217998: Remove method_type field - associated with the appendix field of an indy or method handle call - ---- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index fbcdcf60d9c..158294f7436 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -3192,6 +3192,7 @@ void TemplateTable::prepare_invoke(int byte_no, - // since the parameter_size includes it. - __ push_reg(x9); - __ mv(x9, index); -+ assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0"); - __ load_resolved_reference_at_index(index, x9); - __ pop_reg(x9); - __ push_reg(index); // push appendix (MethodType, CallSite, etc.) - -From 3e50d62dd06c3f8bc586e3ab2b00f2f587d950bf Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:04:31 +0800 -Subject: [PATCH 054/140] Revert JDK-8277372: Add getters for BOT and card - table members - ---- - src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp | 4 ++-- - .../riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp | 6 +++--- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -index 1c46b3947d3..6b75bf63781 100644 ---- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -215,7 +215,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, - ExternalAddress cardtable((address) ct->byte_map_base()); - const Register card_addr = tmp; - -- __ srli(card_addr, store_addr, CardTable::card_shift()); -+ __ srli(card_addr, store_addr, CardTable::card_shift); - - // get the address of the card - __ load_byte_map_base(tmp2); -@@ -437,7 +437,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* - assert_different_registers(card_offset, byte_map_base, t0); - - __ load_parameter(0, card_offset); -- __ srli(card_offset, card_offset, CardTable::card_shift()); -+ __ srli(card_offset, card_offset, CardTable::card_shift); - __ load_byte_map_base(byte_map_base); - - // Convert card offset into an address in card_addr -diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -index a419f92b5f6..868d022ac74 100644 ---- a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -@@ -41,7 +41,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob - BarrierSet* bs = BarrierSet::barrier_set(); - assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - -- __ srli(obj, obj, CardTable::card_shift()); -+ __ srli(obj, obj, CardTable::card_shift); - - assert(CardTable::dirty_card_val() == 0, "must be"); - -@@ -74,8 +74,8 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl - __ shadd(end, count, start, count, LogBytesPerHeapOop); - __ sub(end, end, BytesPerHeapOop); // last element address to make inclusive - -- __ srli(start, start, CardTable::card_shift()); -- __ srli(end, end, CardTable::card_shift()); -+ __ srli(start, start, CardTable::card_shift); -+ __ srli(end, end, CardTable::card_shift); - __ sub(count, end, start); // number of bytes to copy - - __ load_byte_map_base(tmp); - -From 6a81a820e6c08cfdd8e29a835e953dabffdca98a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 19 Apr 2023 11:30:58 +0800 -Subject: [PATCH 055/140] Revert JDK-8260941: Remove the conc_scan parameter - for CardTable - ---- - .../shared/cardTableBarrierSetAssembler_riscv.cpp | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -index 868d022ac74..a476e5ec84d 100644 ---- a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -@@ -41,6 +41,9 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob - BarrierSet* bs = BarrierSet::barrier_set(); - assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - -+ CardTableBarrierSet* ctbs = barrier_set_cast(bs); -+ CardTable* ct = ctbs->card_table(); -+ - __ srli(obj, obj, CardTable::card_shift); - - assert(CardTable::dirty_card_val() == 0, "must be"); -@@ -56,6 +59,9 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob - __ sb(zr, Address(tmp)); - __ bind(L_already_dirty); - } else { -+ if (ct->scanned_concurrently()) { -+ __ membar(MacroAssembler::StoreStore); -+ } - __ sb(zr, Address(tmp)); - } - } -@@ -66,6 +72,10 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl - assert_different_registers(start, tmp); - assert_different_registers(count, tmp); - -+ BarrierSet* bs = BarrierSet::barrier_set(); -+ CardTableBarrierSet* ctbs = barrier_set_cast(bs); -+ CardTable* ct = ctbs->card_table(); -+ - Label L_loop, L_done; - const Register end = count; - -@@ -80,6 +90,9 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl - - __ load_byte_map_base(tmp); - __ add(start, start, tmp); -+ if (ct->scanned_concurrently()) { -+ __ membar(MacroAssembler::StoreStore); -+ } - - __ bind(L_loop); - __ add(tmp, start, count); - -From 24688cb665b16331b491bed2566dc97582a3d73c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 19 Apr 2023 11:32:54 +0800 -Subject: [PATCH 056/140] Revert JDK-8220301: Remove jbyte use in CardTable - -Note: An assertion in `CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier` is removed. See the jdk11u backport for AArch64: https://mail.openjdk.org/pipermail/jdk-updates-dev/2019-August/001746.html ---- - src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp | 3 +++ - .../cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp | 1 + - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/riscv.ad | 3 +-- - 4 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -index 6b75bf63781..b6786c6b327 100644 ---- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -196,6 +196,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, - BarrierSet* bs = BarrierSet::barrier_set(); - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); -+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); - - Label done; - Label runtime; -@@ -213,6 +214,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, - // storing region crossing non-NULL, is card already dirty? - - ExternalAddress cardtable((address) ct->byte_map_base()); -+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); - const Register card_addr = tmp; - - __ srli(card_addr, store_addr, CardTable::card_shift); -@@ -419,6 +421,7 @@ void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* - BarrierSet* bs = BarrierSet::barrier_set(); - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); -+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); - - Label done; - Label runtime; -diff --git a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -index a476e5ec84d..81d47d61d4c 100644 ---- a/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -@@ -43,6 +43,7 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob - - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); -+ assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code"); - - __ srli(obj, obj, CardTable::card_shift); - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index e557a134b5b..6e4d22db40f 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -2719,7 +2719,7 @@ void MacroAssembler::get_thread(Register thread) { - } - - void MacroAssembler::load_byte_map_base(Register reg) { -- CardTable::CardValue* byte_map_base = -+ jbyte *byte_map_base = - ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base(); - li(reg, (uint64_t)byte_map_base); - } -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c2a0be140e9..ca6a232e1e0 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2735,8 +2735,7 @@ operand immByteMapBase() - %{ - // Get base of card map - predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) && -- (CardTable::CardValue*)n->get_ptr() == -- ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); -+ (jbyte*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base()); - match(ConP); - - op_cost(0); - -From 6ee27261d406342a5378d4a404319866a9bae804 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 19 Apr 2023 11:51:20 +0800 -Subject: [PATCH 057/140] Revert JDK-8230486: - G1BarrierSetAssembler::g1_write_barrier_post unnecessarily pushes/pops - new_val - ---- - src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -index b6786c6b327..d724876ec3a 100644 ---- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -250,7 +250,7 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, - - __ bind(runtime); - // save the live input values -- RegSet saved = RegSet::of(store_addr); -+ RegSet saved = RegSet::of(store_addr, new_val); - __ push_reg(saved, sp); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread); - __ pop_reg(saved, sp); - -From 57067a358ffc1b54edfb305549bd460b0fca47f0 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Fri, 21 Apr 2023 12:10:22 +0800 -Subject: [PATCH 058/140] Revert JDK-8242449: AArch64: r27 can be allocated in - CompressedOops mode - ---- - src/hotspot/cpu/riscv/riscv.ad | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index ca6a232e1e0..e3f976faa0d 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -4846,6 +4846,8 @@ instruct storeN(iRegN src, memory mem) - instruct storeImmN0(iRegIHeapbase heapbase, immN0 zero, memory mem) - %{ - match(Set mem (StoreN mem zero)); -+ predicate(Universe::narrow_oop_base() == NULL && -+ Universe::narrow_klass_base() == NULL); - - ins_cost(STORE_COST); - format %{ "sw rheapbase, $mem\t# compressed ptr (rheapbase==0), #@storeImmN0" %} - -From 0db520768d4d268a9dc641e301df45653c52f6eb Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 23 Apr 2023 14:59:09 +0800 -Subject: [PATCH 059/140] A fix for interpreter frame verification code, - skipping the locals check if there is no locals. See one of the additional - commits in JDK-8286301, the RISC-V loom port. - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 11 ++++++++++- - 1 file changed, 10 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index d03adc0bff4..13c482b610a 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -571,7 +571,16 @@ bool frame::is_interpreted_frame_valid(JavaThread* thread) const { - - // validate locals - address locals = (address) *interpreter_frame_locals_addr(); -- if (locals > thread->stack_base() || locals < (address) fp()) { -+ if (locals > thread->stack_base()) { -+ return false; -+ } -+ -+ if (m->max_locals() > 0 && locals < (address) fp()) { -+ // fp in interpreter frame on RISC-V is higher than that on AArch64, -+ // pointing to sender_sp and sender_sp-2 relatively. -+ // On RISC-V, if max_locals is 0, the 'locals' pointer may be below fp, -+ // pointing to sender_sp-1 (with one padding slot). -+ // So we verify the 'locals' pointer only if max_locals > 0. - return false; - } - - -From 795da5afe59658b4d89cd8501b4f4ec56471b14c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 11 Apr 2023 11:45:40 +0800 -Subject: [PATCH 060/140] ShenandoahGC adaptations on JDK11 for RISC-V backend - ---- - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 4 +- - .../c1/shenandoahBarrierSetC1_riscv.cpp | 2 +- - .../shenandoahBarrierSetAssembler_riscv.cpp | 229 +++++++++--------- - .../shenandoahBarrierSetAssembler_riscv.hpp | 15 +- - .../riscv/gc/shenandoah/shenandoah_riscv64.ad | 88 ------- - src/hotspot/cpu/riscv/riscv.ad | 6 +- - .../templateInterpreterGenerator_riscv.cpp | 15 +- - 7 files changed, 146 insertions(+), 213 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 6a961ee2307..90c4af5d3b0 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -1817,10 +1817,12 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) { - - - void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { -- if (patch_code != lir_patch_none) { -+#if INCLUDE_SHENANDOAHGC -+ if (UseShenandoahGC && patch_code != lir_patch_none) { - deoptimize_trap(info); - return; - } -+#endif - - assert(patch_code == lir_patch_none, "Patch code not supported"); - LIR_Address* adr = addr->as_address_ptr(); -diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp -index cd568cc723f..d19f5b859ce 100644 ---- a/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shenandoah/c1/shenandoahBarrierSetC1_riscv.cpp -@@ -103,7 +103,7 @@ LIR_Opr ShenandoahBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRIt - __ xchg(access.resolved_addr(), value_opr, result, tmp); - - if (access.is_oop()) { -- result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0), access.decorators()); -+ result = load_reference_barrier(access.gen(), result, LIR_OprFact::addressConst(0)); - LIR_Opr tmp_opr = gen->new_register(type); - __ move(result, tmp_opr); - result = tmp_opr; -diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -index 84e1205bc25..b8534c52e77 100644 ---- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp -@@ -27,7 +27,7 @@ - #include "gc/shenandoah/shenandoahBarrierSet.hpp" - #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" - #include "gc/shenandoah/shenandoahForwarding.hpp" --#include "gc/shenandoah/shenandoahHeap.inline.hpp" -+#include "gc/shenandoah/shenandoahHeap.hpp" - #include "gc/shenandoah/shenandoahHeapRegion.hpp" - #include "gc/shenandoah/shenandoahRuntime.hpp" - #include "gc/shenandoah/shenandoahThreadLocalData.hpp" -@@ -44,6 +44,8 @@ - - #define __ masm-> - -+address ShenandoahBarrierSetAssembler::_shenandoah_lrb = NULL; -+ - void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, - Register src, Register dst, Register count, RegSet saved_regs) { - if (is_oop) { -@@ -116,10 +118,10 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, - Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())); - - // Is marking active? -- if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { -+ if (in_bytes(ShenandoahSATBMarkQueue::byte_width_of_active()) == 4) { - __ lwu(tmp, in_progress); - } else { -- assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); -+ assert(in_bytes(ShenandoahSATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); - __ lbu(tmp, in_progress); - } - __ beqz(tmp, done); -@@ -225,37 +227,21 @@ void ShenandoahBarrierSetAssembler::resolve_forward_pointer_not_null(MacroAssemb - __ pop_reg(saved_regs, sp); - } - --void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, -- Register dst, -- Address load_addr, -- DecoratorSet decorators) { -+void ShenandoahBarrierSetAssembler::load_reference_barrier_not_null(MacroAssembler* masm, -+ Register dst, -+ Address load_addr) { - assert(ShenandoahLoadRefBarrier, "Should be enabled"); - assert(dst != t1 && load_addr.base() != t1, "need t1"); - assert_different_registers(load_addr.base(), t0, t1); - -- bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -- bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -- bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -- bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -- bool is_narrow = UseCompressedOops && !is_native; -- -- Label heap_stable, not_cset; -+ Label done; - __ enter(); - Address gc_state(xthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset())); - __ lbu(t1, gc_state); - - // Check for heap stability -- if (is_strong) { -- __ andi(t1, t1, ShenandoahHeap::HAS_FORWARDED); -- __ beqz(t1, heap_stable); -- } else { -- Label lrb; -- __ andi(t0, t1, ShenandoahHeap::WEAK_ROOTS); -- __ bnez(t0, lrb); -- __ andi(t0, t1, ShenandoahHeap::HAS_FORWARDED); -- __ beqz(t0, heap_stable); -- __ bind(lrb); -- } -+ __ andi(t1, t1, ShenandoahHeap::HAS_FORWARDED); -+ __ beqz(t1, done); - - // use x11 for load address - Register result_dst = dst; -@@ -270,43 +256,12 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, - __ la(x11, load_addr); - __ mv(x10, dst); - -- // Test for in-cset -- if (is_strong) { -- __ li(t1, (uint64_t)ShenandoahHeap::in_cset_fast_test_addr()); -- __ srli(t0, x10, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -- __ add(t1, t1, t0); -- __ lbu(t1, Address(t1)); -- __ andi(t0, t1, 1); -- __ beqz(t0, not_cset); -- } -+ __ far_call(RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahBarrierSetAssembler::shenandoah_lrb()))); - -- __ push_call_clobbered_registers(); -- if (is_strong) { -- if (is_narrow) { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); -- } else { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -- } -- } else if (is_weak) { -- if (is_narrow) { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); -- } else { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -- } -- } else { -- assert(is_phantom, "only remaining strength"); -- assert(!is_narrow, "phantom access cannot be narrow"); -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -- } -- __ jalr(ra); -- __ mv(t0, x10); -- __ pop_call_clobbered_registers(); -- __ mv(x10, t0); -- __ bind(not_cset); - __ mv(result_dst, x10); - __ pop_reg(saved_regs, sp); - -- __ bind(heap_stable); -+ __ bind(done); - __ leave(); - } - -@@ -320,6 +275,15 @@ void ShenandoahBarrierSetAssembler::iu_barrier(MacroAssembler* masm, Register ds - } - } - -+void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr) { -+ if (ShenandoahLoadRefBarrier) { -+ Label is_null; -+ __ beqz(dst, is_null); -+ load_reference_barrier_not_null(masm, dst, load_addr); -+ __ bind(is_null); -+ } -+} -+ - // - // Arguments: - // -@@ -363,7 +327,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, - - BarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread); - -- load_reference_barrier(masm, dst, src, decorators); -+ load_reference_barrier(masm, dst, src); - - if (dst != result_dst) { - __ mv(result_dst, dst); -@@ -555,7 +519,7 @@ void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, Shen - Register pre_val_reg = stub->pre_val()->as_register(); - - if (stub->do_load()) { -- ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); -+ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */, false /*unaligned*/); - } - __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); - ce->store_parameter(stub->pre_val()->as_register(), 0); -@@ -568,12 +532,6 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble - ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1(); - __ bind(*stub->entry()); - -- DecoratorSet decorators = stub->decorators(); -- bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -- bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -- bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -- bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -- - Register obj = stub->obj()->as_register(); - Register res = stub->result()->as_register(); - Register addr = stub->addr()->as_pointer_register(); -@@ -587,30 +545,32 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble - __ mv(res, obj); - } - -- if (is_strong) { -- // Check for object in cset. -- __ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr()); -- __ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -- __ add(tmp2, tmp2, tmp1); -- __ lbu(tmp2, Address(tmp2)); -- __ beqz(tmp2, *stub->continuation(), true /* is_far */); -- } -+ // Check for null. -+ __ beqz(res, *stub->continuation(), /* is_far */ true); -+ -+ // Check for object in cset. -+ __ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr()); -+ __ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -+ __ add(t0, tmp2, tmp1); -+ __ lb(tmp2, Address(t0)); -+ __ beqz(tmp2, *stub->continuation(), /* is_far */ true); -+ -+ // Check if object is already forwarded. -+ Label slow_path; -+ __ ld(tmp1, Address(res, oopDesc::mark_offset_in_bytes())); -+ __ xori(tmp1, tmp1, -1); -+ __ andi(t0, tmp1, markOopDesc::lock_mask_in_place); -+ __ bnez(t0, slow_path); -+ -+ // Decode forwarded object. -+ __ ori(tmp1, tmp1, markOopDesc::marked_value); -+ __ xori(res, tmp1, -1); -+ __ j(*stub->continuation()); - -+ __ bind(slow_path); - ce->store_parameter(res, 0); - ce->store_parameter(addr, 1); -- -- if (is_strong) { -- if (is_native) { -- __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin())); -- } else { -- __ far_call(RuntimeAddress(bs->load_reference_barrier_strong_rt_code_blob()->code_begin())); -- } -- } else if (is_weak) { -- __ far_call(RuntimeAddress(bs->load_reference_barrier_weak_rt_code_blob()->code_begin())); -- } else { -- assert(is_phantom, "only remaining strength"); -- __ far_call(RuntimeAddress(bs->load_reference_barrier_phantom_rt_code_blob()->code_begin())); -- } -+ __ far_call(RuntimeAddress(bs->load_reference_barrier_rt_code_blob()->code_begin())); - - __ j(*stub->continuation()); - } -@@ -664,8 +624,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss - __ epilogue(); - } - --void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, -- DecoratorSet decorators) { -+void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm) { - __ prologue("shenandoah_load_reference_barrier", false); - // arg0 : object to be resolved - -@@ -673,31 +632,10 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s - __ load_parameter(0, x10); - __ load_parameter(1, x11); - -- bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators); -- bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators); -- bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators); -- bool is_native = ShenandoahBarrierSet::is_native_access(decorators); -- if (is_strong) { -- if (is_native) { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -- } else { -- if (UseCompressedOops) { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong_narrow); -- } else { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_strong); -- } -- } -- } else if (is_weak) { -- assert(!is_native, "weak must not be called off-heap"); -- if (UseCompressedOops) { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak_narrow); -- } else { -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_weak); -- } -+ if (UseCompressedOops) { -+ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow)); - } else { -- assert(is_phantom, "only remaining strength"); -- assert(is_native, "phantom must only be called off-heap"); -- __ li(ra, (int64_t)(uintptr_t)ShenandoahRuntime::load_reference_barrier_phantom); -+ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier)); - } - __ jalr(ra); - __ mv(t0, x10); -@@ -710,3 +648,68 @@ void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_s - #undef __ - - #endif // COMPILER1 -+ -+address ShenandoahBarrierSetAssembler::shenandoah_lrb() { -+ assert(_shenandoah_lrb != NULL, "need load reference barrier stub"); -+ return _shenandoah_lrb; -+} -+ -+#define __ cgen->assembler()-> -+ -+// Shenandoah load reference barrier. -+// -+// Input: -+// x10: OOP to evacuate. Not null. -+// x11: load address -+// -+// Output: -+// x10: Pointer to evacuated OOP. -+// -+// Trash t0 t1 Preserve everything else. -+address ShenandoahBarrierSetAssembler::generate_shenandoah_lrb(StubCodeGenerator* cgen) { -+ __ align(6); -+ StubCodeMark mark(cgen, "StubRoutines", "shenandoah_lrb"); -+ address start = __ pc(); -+ -+ Label slow_path; -+ __ mv(t1, ShenandoahHeap::in_cset_fast_test_addr()); -+ __ srli(t0, x10, ShenandoahHeapRegion::region_size_bytes_shift_jint()); -+ __ add(t1, t1, t0); -+ __ lbu(t1, Address(t1, 0)); -+ __ andi(t0, t1, 1); -+ __ bnez(t0, slow_path); -+ __ ret(); -+ -+ __ bind(slow_path); -+ __ enter(); // required for proper stackwalking of RuntimeStub frame -+ -+ __ push_call_clobbered_registers(); -+ -+ if (UseCompressedOops) { -+ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_narrow)); -+ } else { -+ __ mv(ra, CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier)); -+ } -+ __ jalr(ra); -+ __ mv(t0, x10); -+ __ pop_call_clobbered_registers(); -+ __ mv(x10, t0); -+ -+ __ leave(); // required for proper stackwalking of RuntimeStub frame -+ __ ret(); -+ -+ return start; -+} -+ -+#undef __ -+ -+void ShenandoahBarrierSetAssembler::barrier_stubs_init() { -+ if (ShenandoahLoadRefBarrier) { -+ int stub_code_size = 2048; -+ ResourceMark rm; -+ BufferBlob* bb = BufferBlob::create("shenandoah_barrier_stubs", stub_code_size); -+ CodeBuffer buf(bb); -+ StubCodeGenerator cgen(&buf); -+ _shenandoah_lrb = generate_shenandoah_lrb(&cgen); -+ } -+} -diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp -index a705f497667..5d75035e9d4 100644 ---- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.hpp -@@ -40,6 +40,8 @@ class StubCodeGenerator; - class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { - private: - -+ static address _shenandoah_lrb; -+ - void satb_write_barrier_pre(MacroAssembler* masm, - Register obj, - Register pre_val, -@@ -57,17 +59,22 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { - - void resolve_forward_pointer(MacroAssembler* masm, Register dst, Register tmp = noreg); - void resolve_forward_pointer_not_null(MacroAssembler* masm, Register dst, Register tmp = noreg); -- void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr, DecoratorSet decorators); -+ void load_reference_barrier(MacroAssembler* masm, Register dst, Address load_addr); -+ void load_reference_barrier_not_null(MacroAssembler* masm, Register dst, Address load_addr); -+ -+ address generate_shenandoah_lrb(StubCodeGenerator* cgen); - - public: - -+ static address shenandoah_lrb(); -+ - void iu_barrier(MacroAssembler* masm, Register dst, Register tmp); - - #ifdef COMPILER1 - void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub); - void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub); - void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm); -- void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators); -+ void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm); - #endif - - virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop, -@@ -81,8 +88,10 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { - virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, - Register obj, Register tmp, Label& slowpath); - -- void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, -+ virtual void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, - Assembler::Aqrl acquire, Assembler::Aqrl release, bool is_cae, Register result); -+ -+ virtual void barrier_stubs_init(); - }; - - #endif // CPU_RISCV_GC_SHENANDOAH_SHENANDOAHBARRIERSETASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad -index 6c855f23c2a..bab407a8b76 100644 ---- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad -+++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoah_riscv64.ad -@@ -176,48 +176,6 @@ instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldva - ins_pipe(pipe_slow); - %} - --instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ -- predicate(needs_acquiring_load_reserved(n)); -- match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval))); -- ins_cost(10 * DEFAULT_COST); -- -- effect(TEMP_DEF res, TEMP tmp, KILL cr); -- format %{ -- "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangeNAcq_shenandoah" -- %} -- -- ins_encode %{ -- Register tmp = $tmp$$Register; -- __ mv(tmp, $oldval$$Register); -- ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -- Assembler::aq /* acquire */, Assembler::rl /* release */, -- true /* is_cae */, $res$$Register); -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ -- predicate(needs_acquiring_load_reserved(n)); -- match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval))); -- ins_cost(10 * DEFAULT_COST); -- -- effect(TEMP_DEF res, TEMP tmp, KILL cr); -- format %{ -- "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval, #@compareAndExchangePAcq_shenandoah" -- %} -- -- ins_encode %{ -- Register tmp = $tmp$$Register; -- __ mv(tmp, $oldval$$Register); -- ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -- Assembler::aq /* acquire */, Assembler::rl /* release */, -- true /* is_cae */, $res$$Register); -- %} -- -- ins_pipe(pipe_slow); --%} -- - instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ - match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); - ins_cost(10 * DEFAULT_COST); -@@ -237,49 +195,3 @@ instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldva - - ins_pipe(pipe_slow); - %} -- --instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, iRegNNoSp tmp, rFlagsReg cr) %{ -- predicate(needs_acquiring_load_reserved(n)); -- match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval))); -- ins_cost(10 * DEFAULT_COST); -- -- effect(TEMP tmp, KILL cr); -- format %{ -- "cmpxchgw_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapNAcq_shenandoah" -- "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" -- %} -- -- ins_encode %{ -- Register tmp = $tmp$$Register; -- __ mv(tmp, $oldval$$Register); // Must not clobber oldval. -- // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop -- ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -- Assembler::aq /* acquire */, Assembler::rl /* release */, -- false /* is_cae */, $res$$Register); -- %} -- -- ins_pipe(pipe_slow); --%} -- --instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, rFlagsReg cr) %{ -- predicate(needs_acquiring_load_reserved(n)); -- match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval))); -- ins_cost(10 * DEFAULT_COST); -- -- effect(TEMP tmp, KILL cr); -- format %{ -- "cmpxchg_acq_shenandoah $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval, #@weakCompareAndSwapPAcq_shenandoah" -- "mv $res, EQ\t# $res <-- (EQ ? 1 : 0)" -- %} -- -- ins_encode %{ -- Register tmp = $tmp$$Register; -- __ mv(tmp, $oldval$$Register); // Must not clobber oldval. -- // Weak is not current supported by ShenandoahBarrierSet::cmpxchg_oop -- ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, -- Assembler::aq /* acquire */, Assembler::rl /* release */, -- false /* is_cae */, $res$$Register); -- %} -- -- ins_pipe(pipe_slow); --%} -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index e3f976faa0d..a6061de7a33 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -828,8 +828,10 @@ bool is_CAS(int opcode, bool maybe_volatile) - case Op_CompareAndSwapL: - case Op_CompareAndSwapP: - case Op_CompareAndSwapN: -+#if INCLUDE_SHENANDOAHGC - case Op_ShenandoahCompareAndSwapP: - case Op_ShenandoahCompareAndSwapN: -+#endif - case Op_CompareAndSwapB: - case Op_CompareAndSwapS: - case Op_GetAndSetI: -@@ -851,10 +853,6 @@ bool is_CAS(int opcode, bool maybe_volatile) - case Op_WeakCompareAndSwapL: - case Op_WeakCompareAndSwapP: - case Op_WeakCompareAndSwapN: -- case Op_ShenandoahWeakCompareAndSwapP: -- case Op_ShenandoahWeakCompareAndSwapN: -- case Op_ShenandoahCompareAndExchangeP: -- case Op_ShenandoahCompareAndExchangeN: - return maybe_volatile; - default: - return false; -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index a07dea35b73..5a87c687cf7 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -765,9 +765,18 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { - __ sd(ProfileInterpreter ? t0 : zr, Address(sp, 6 * wordSize)); - - // Get mirror and store it in the frame as GC root for this Method* -- __ load_mirror(t2, xmethod); -- __ sd(zr, Address(sp, 5 * wordSize)); -- __ sd(t2, Address(sp, 4 * wordSize)); -+#if INCLUDE_SHENANDOAHGC -+ if (UseShenandoahGC) { -+ __ load_mirror(x28, xmethod); -+ __ sd(zr, Address(sp, 5 * wordSize)); -+ __ sd(x28, Address(sp, 4 * wordSize)); -+ } else -+#endif -+ { -+ __ load_mirror(t2, xmethod); -+ __ sd(zr, Address(sp, 5 * wordSize)); -+ __ sd(t2, Address(sp, 4 * wordSize)); -+ } - - __ ld(xcpool, Address(xmethod, Method::const_offset())); - __ ld(xcpool, Address(xcpool, ConstMethod::constants_offset())); - -From d8b14fd5e6455b47cfcb02d13c0c24c74e824570 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 14:42:07 +0800 -Subject: [PATCH 061/140] Revert JDK-8248404: AArch64: Remove uses of long and - unsigned long - ---- - src/hotspot/cpu/riscv/assembler_riscv.hpp | 19 +++++++++++++------ - .../cpu/riscv/macroAssembler_riscv.cpp | 6 ------ - .../cpu/riscv/macroAssembler_riscv.hpp | 13 ++++++++----- - 3 files changed, 21 insertions(+), 17 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp -index 51aa052a0c7..31aeeb9b425 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -183,13 +183,20 @@ class Address { - : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } - Address(Register r) - : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } -- -- template::value)> -- Address(Register r, T o) -- : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) {} -- -+ Address(Register r, int o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+ Address(Register r, long o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+ Address(Register r, long long o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+ Address(Register r, unsigned int o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+ Address(Register r, unsigned long o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+ Address(Register r, unsigned long long o) -+ : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } - Address(Register r, ByteSize disp) -- : Address(r, in_bytes(disp)) {} -+ : Address(r, in_bytes(disp)) { } - Address(address target, RelocationHolder const& rspec) - : _base(noreg), - _index(noreg), -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 6e4d22db40f..b95f69cfcda 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1364,12 +1364,6 @@ void MacroAssembler::mv(Register Rd, Address dest) { - movptr(Rd, dest.target()); - } - --void MacroAssembler::mv(Register Rd, address addr) { -- // Here in case of use with relocation, use fix length instruciton -- // movptr instead of li -- movptr(Rd, addr); --} -- - void MacroAssembler::mv(Register Rd, RegisterOrConstant src) { - if (src.is_register()) { - mv(Rd, src.as_register()); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index c1ffa120774..76b2716659b 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -543,15 +543,18 @@ class MacroAssembler: public Assembler { - } - - // mv -- template::value)> -- inline void mv(Register Rd, T o) { -- li(Rd, (int64_t)o); -- } -+ void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); } -+ -+ inline void mv(Register Rd, int imm64) { li(Rd, (int64_t)imm64); } -+ inline void mv(Register Rd, long imm64) { li(Rd, (int64_t)imm64); } -+ inline void mv(Register Rd, long long imm64) { li(Rd, (int64_t)imm64); } -+ inline void mv(Register Rd, unsigned int imm64) { li(Rd, (int64_t)imm64); } -+ inline void mv(Register Rd, unsigned long imm64) { li(Rd, (int64_t)imm64); } -+ inline void mv(Register Rd, unsigned long long imm64) { li(Rd, (int64_t)imm64); } - - inline void mvw(Register Rd, int32_t imm32) { mv(Rd, imm32); } - - void mv(Register Rd, Address dest); -- void mv(Register Rd, address addr); - void mv(Register Rd, RegisterOrConstant src); - - // logic - -From 94c1c9c01e61d0cb7c32596ef19b347c32406546 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 16:54:36 +0800 -Subject: [PATCH 062/140] Revert JDK-8280503: Use allStatic.hpp instead of - allocation.hpp where possible - ---- - src/hotspot/cpu/riscv/bytes_riscv.hpp | 2 -- - src/hotspot/cpu/riscv/jniTypes_riscv.hpp | 1 - - 2 files changed, 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/bytes_riscv.hpp b/src/hotspot/cpu/riscv/bytes_riscv.hpp -index 23d982f9abd..f60e0e38ae8 100644 ---- a/src/hotspot/cpu/riscv/bytes_riscv.hpp -+++ b/src/hotspot/cpu/riscv/bytes_riscv.hpp -@@ -27,8 +27,6 @@ - #ifndef CPU_RISCV_BYTES_RISCV_HPP - #define CPU_RISCV_BYTES_RISCV_HPP - --#include "memory/allStatic.hpp" -- - class Bytes: AllStatic { - public: - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering -diff --git a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -index 83ffcc55d83..bc4e5758256 100644 ---- a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -+++ b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -@@ -27,7 +27,6 @@ - #define CPU_RISCV_JNITYPES_RISCV_HPP - - #include "jni.h" --#include "memory/allStatic.hpp" - #include "oops/oop.hpp" - - // This file holds platform-dependent routines used to write primitive jni - -From 49e6399009b51edafa6904164528e1d051aeae6c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:07:31 +0800 -Subject: [PATCH 063/140] Revert JDK-8276453: Undefined behavior in C1 - LIR_OprDesc causes SEGV in fastdebug build - ---- - src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 4 ++-- - src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp | 4 ++-- - src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp | 1 + - 3 files changed, 5 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -index af7bd067f33..6057d43296b 100644 ---- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -@@ -58,7 +58,7 @@ RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, LIR_Opr array) - } - - RangeCheckStub::RangeCheckStub(CodeEmitInfo* info, LIR_Opr index) -- : _index(index), _array(), _throw_index_out_of_bounds_exception(true) { -+ : _index(index), _array(NULL), _throw_index_out_of_bounds_exception(true) { - assert(info != NULL, "must have info"); - _info = new CodeEmitInfo(info); - } -@@ -83,7 +83,7 @@ void RangeCheckStub::emit_code(LIR_Assembler* ce) { - if (_throw_index_out_of_bounds_exception) { - stub_id = Runtime1::throw_index_exception_id; - } else { -- assert(_array != LIR_Opr::nullOpr(), "sanity"); -+ assert(_array != NULL, "sanity"); - __ mv(t1, _array->as_pointer_register()); - stub_id = Runtime1::throw_range_check_failed_id; - } -diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -index 172031941b2..1f8b2b55100 100644 ---- a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -@@ -156,8 +156,8 @@ LIR_Opr FrameMap::long11_opr; - LIR_Opr FrameMap::fpu10_float_opr; - LIR_Opr FrameMap::fpu10_double_opr; - --LIR_Opr FrameMap::_caller_save_cpu_regs[] = {}; --LIR_Opr FrameMap::_caller_save_fpu_regs[] = {}; -+LIR_Opr FrameMap::_caller_save_cpu_regs[] = { 0, }; -+LIR_Opr FrameMap::_caller_save_fpu_regs[] = { 0, }; - - //-------------------------------------------------------- - // FrameMap -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index c45a75b2301..227e7664225 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -206,6 +206,7 @@ LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) { - break; - default: - ShouldNotReachHere(); -+ r = NULL; - } - return r; - } - -From b94bda9d1a2c12fa379f8fe813460c498344f543 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:19:19 +0800 -Subject: [PATCH 064/140] Revert JDK-8256205: Simplify compiler calling - convention handling - ---- - src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/riscv.ad | 25 +++++++++++++++++++ - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 11 ++------ - 4 files changed, 29 insertions(+), 11 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -index 6057d43296b..12980c12de6 100644 ---- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp -@@ -290,7 +290,7 @@ void ArrayCopyStub::emit_code(LIR_Assembler* ce) { - const int args_num = 5; - VMRegPair args[args_num]; - BasicType signature[args_num] = { T_OBJECT, T_INT, T_OBJECT, T_INT, T_INT }; -- SharedRuntime::java_calling_convention(signature, args, args_num); -+ SharedRuntime::java_calling_convention(signature, args, args_num, true); - - // push parameters - Register r[args_num]; -diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -index 1f8b2b55100..682ebe82627 100644 ---- a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp -@@ -314,7 +314,7 @@ void FrameMap::initialize() { - - VMRegPair regs; - BasicType sig_bt = T_OBJECT; -- SharedRuntime::java_calling_convention(&sig_bt, ®s, 1); -+ SharedRuntime::java_calling_convention(&sig_bt, ®s, 1, true); - receiver_opr = as_oop_opr(regs.first()->as_Register()); - - for (i = 0; i < nof_caller_save_fpu_regs; i++) { -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index a6061de7a33..1667994699f 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2443,6 +2443,12 @@ frame %{ - // Stack alignment requirement - stack_alignment(StackAlignmentInBytes); // Alignment size in bytes (128-bit -> 16 bytes) - -+ // Number of stack slots between incoming argument block and the start of -+ // a new frame. The PROLOG must add this many slots to the stack. The -+ // EPILOG must remove this many slots. RISC-V needs two slots for -+ // return address and fp. -+ in_preserve_stack_slots(2 * VMRegImpl::slots_per_word); -+ - // Number of outgoing stack slots killed above the out_preserve_stack_slots - // for calls to C. Supports the var-args backing area for register parms. - varargs_C_out_slots_killed(frame::arg_reg_save_area_bytes / BytesPerInt); -@@ -2461,6 +2467,25 @@ frame %{ - Compile::current()->fixed_slots()), - stack_alignment_in_slots())); - -+ // Body of function which returns an integer array locating -+ // arguments either in registers or in stack slots. Passed an array -+ // of ideal registers called "sig" and a "length" count. Stack-slot -+ // offsets are based on outgoing arguments, i.e. a CALLER setting up -+ // arguments for a CALLEE. Incoming stack arguments are -+ // automatically biased by the preserve_stack_slots field above. -+ -+ calling_convention -+ %{ -+ // No difference between ingoing/outgoing just pass false -+ SharedRuntime::java_calling_convention(sig_bt, regs, length, false); -+ %} -+ -+ c_calling_convention -+ %{ -+ // This is obviously always outgoing -+ (void) SharedRuntime::c_calling_convention(sig_bt, regs, NULL, length); -+ %} -+ - // Location of compiled Java return values. Same as C for now. - return_value - %{ -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index eaefcc2b595..411bddd2ace 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -233,7 +233,8 @@ static int reg2offset_out(VMReg r) { - - int SharedRuntime::java_calling_convention(const BasicType *sig_bt, - VMRegPair *regs, -- int total_args_passed) { -+ int total_args_passed, -+ int is_outgoing) { - // Create the mapping between argument positions and - // registers. - static const Register INT_ArgReg[Argument::n_int_register_parameters_j] = { -@@ -2155,14 +2156,6 @@ void SharedRuntime::generate_deopt_blob() { - _deopt_blob->set_unpack_with_exception_in_tls_offset(exception_in_tls_offset); - } - --// Number of stack slots between incoming argument block and the start of --// a new frame. The PROLOG must add this many slots to the stack. The --// EPILOG must remove this many slots. --// RISCV needs two words for RA (return address) and FP (frame pointer). --uint SharedRuntime::in_preserve_stack_slots() { -- return 2 * VMRegImpl::slots_per_word; --} -- - uint SharedRuntime::out_preserve_stack_slots() { - return 0; - } - -From 3fc948472c4a0918b967646b45c8886103b839d2 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:27:57 +0800 -Subject: [PATCH 065/140] Revert JDK-8183574: Unify the is_power_of_2 functions - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp | 4 ++-- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 1 - - src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp | 3 +-- - src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 1 - - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 1 - - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 1 - - src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 1 - - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 1 - - src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp | 1 - - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 1 - - 10 files changed, 3 insertions(+), 12 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -index 4c1c13dc290..65d0eda62ef 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -@@ -190,7 +190,7 @@ void LIR_Assembler::arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr rig - code == lir_add ? __ add(dreg, lreg_lo, c) : __ sub(dreg, lreg_lo, c); - break; - case lir_div: -- assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); -+ assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); - if (c == 1) { - // move lreg_lo to dreg if divisor is 1 - __ mv(dreg, lreg_lo); -@@ -208,7 +208,7 @@ void LIR_Assembler::arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr rig - } - break; - case lir_rem: -- assert(c > 0 && is_power_of_2(c), "divisor must be power-of-2 constant"); -+ assert(c > 0 && is_power_of_2_long(c), "divisor must be power-of-2 constant"); - if (c == 1) { - // move 0 to dreg if divisor is 1 - __ mv(dreg, zr); -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 90c4af5d3b0..9de89a3b026 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -41,7 +41,6 @@ - #include "oops/objArrayKlass.hpp" - #include "runtime/frame.inline.hpp" - #include "runtime/sharedRuntime.hpp" --#include "utilities/powerOfTwo.hpp" - #include "vmreg_riscv.inline.hpp" - - #ifndef PRODUCT -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index 227e7664225..a9345158749 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -38,7 +38,6 @@ - #include "ci/ciTypeArrayKlass.hpp" - #include "runtime/sharedRuntime.hpp" - #include "runtime/stubRoutines.hpp" --#include "utilities/powerOfTwo.hpp" - #include "vmreg_riscv.inline.hpp" - - #ifdef ASSERT -@@ -383,7 +382,7 @@ void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { - // no need to do div-by-zero check if the divisor is a non-zero constant - if (c != 0) { need_zero_check = false; } - // do not load right if the divisor is a power-of-2 constant -- if (c > 0 && is_power_of_2(c)) { -+ if (c > 0 && is_power_of_2_long(c)) { - right.dont_load_item(); - } else { - right.load_item(); -diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -index 1f45fba9de0..fc88d5c180e 100644 ---- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -@@ -46,7 +46,6 @@ - #include "runtime/stubRoutines.hpp" - #include "runtime/vframe.hpp" - #include "runtime/vframeArray.hpp" --#include "utilities/powerOfTwo.hpp" - #include "vmreg_riscv.inline.hpp" - - -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index f0c249f0d26..2fc0b00e2cb 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -44,7 +44,6 @@ - #include "runtime/safepointMechanism.hpp" - #include "runtime/sharedRuntime.hpp" - #include "runtime/thread.inline.hpp" --#include "utilities/powerOfTwo.hpp" - - void InterpreterMacroAssembler::narrow(Register result) { - // Get method->_constMethod->_result_type -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index b95f69cfcda..41a415ef2cf 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -47,7 +47,6 @@ - #include "runtime/sharedRuntime.hpp" - #include "runtime/stubRoutines.hpp" - #include "runtime/thread.hpp" --#include "utilities/powerOfTwo.hpp" - #ifdef COMPILER2 - #include "opto/compile.hpp" - #include "opto/node.hpp" -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 76b2716659b..dd39f67d507 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -30,7 +30,6 @@ - #include "asm/assembler.hpp" - #include "metaprogramming/enableIf.hpp" - #include "oops/compressedOops.hpp" --#include "utilities/powerOfTwo.hpp" - - // MacroAssembler extends Assembler by frequently used macros. - // -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index 8392b768847..0c5b0e001ee 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -45,7 +45,6 @@ - #include "runtime/stubRoutines.hpp" - #include "runtime/thread.inline.hpp" - #include "utilities/align.hpp" --#include "utilities/powerOfTwo.hpp" - #ifdef COMPILER2 - #include "opto/runtime.hpp" - #endif -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index 5a87c687cf7..a10677bf650 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -51,7 +51,6 @@ - #include "runtime/timer.hpp" - #include "runtime/vframeArray.hpp" - #include "utilities/debug.hpp" --#include "utilities/powerOfTwo.hpp" - #include - - #ifndef PRODUCT -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index 158294f7436..2a92fb9dd49 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -44,7 +44,6 @@ - #include "runtime/sharedRuntime.hpp" - #include "runtime/stubRoutines.hpp" - #include "runtime/synchronizer.hpp" --#include "utilities/powerOfTwo.hpp" - - #define __ _masm-> - - -From 31b18aa6a29b83e2cae7ea76c5d4759b2596eca0 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:34:39 +0800 -Subject: [PATCH 066/140] Revert JDK-8276976: Rename LIR_OprDesc to LIR_Opr - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/c1_LIR_riscv.cpp | 14 +++++++------- - 2 files changed, 8 insertions(+), 8 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 9de89a3b026..70ee6295bfb 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -1261,7 +1261,7 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { - assert(op->addr()->is_address(), "what else?"); - LIR_Address* addr_ptr = op->addr()->as_address_ptr(); - assert(addr_ptr->disp() == 0, "need 0 disp"); -- assert(addr_ptr->index() == LIR_Opr::illegalOpr(), "need 0 index"); -+ assert(addr_ptr->index() == LIR_OprDesc::illegalOpr(), "need 0 index"); - addr = as_reg(addr_ptr->base()); - } - Register newval = as_reg(op->new_value()); -diff --git a/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp -index 5f1c394ab3d..0317ed9003e 100644 ---- a/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIR_riscv.cpp -@@ -27,22 +27,22 @@ - #include "asm/register.hpp" - #include "c1/c1_LIR.hpp" - --FloatRegister LIR_Opr::as_float_reg() const { -+FloatRegister LIR_OprDesc::as_float_reg() const { - return as_FloatRegister(fpu_regnr()); - } - --FloatRegister LIR_Opr::as_double_reg() const { -+FloatRegister LIR_OprDesc::as_double_reg() const { - return as_FloatRegister(fpu_regnrLo()); - } - - // Reg2 unused. - LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { - assert(as_FloatRegister(reg2) == fnoreg, "Not used on this platform"); -- return (LIR_Opr)(intptr_t)((reg1 << LIR_Opr::reg1_shift) | -- (reg1 << LIR_Opr::reg2_shift) | -- LIR_Opr::double_type | -- LIR_Opr::fpu_register | -- LIR_Opr::double_size); -+ return (LIR_Opr)(intptr_t)((reg1 << LIR_OprDesc::reg1_shift) | -+ (reg1 << LIR_OprDesc::reg2_shift) | -+ LIR_OprDesc::double_type | -+ LIR_OprDesc::fpu_register | -+ LIR_OprDesc::double_size); - } - - #ifndef PRODUCT - -From 2e64fa47eddc271d32b136ace4f062cfb9648b25 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:39:16 +0800 -Subject: [PATCH 067/140] Revert JDK-8269672: C1: Remove unaligned move on all - architectures - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 8 +++++--- - .../cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp | 2 +- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 70ee6295bfb..e29c0df5f8b 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -673,7 +673,7 @@ void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool po - } - } - --void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide) { -+void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide, bool /* unaligned */) { - LIR_Address* to_addr = dest->as_address_ptr(); - // t0 was used as tmp reg in as_Address, so we use t1 as compressed_src - Register compressed_src = t1; -@@ -795,7 +795,7 @@ void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { - reg2stack(temp, dest, dest->type(), false); - } - --void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide) { -+void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool /* unaligned */) { - assert(src->is_address(), "should not call otherwise"); - assert(dest->is_register(), "should not call otherwise"); - -@@ -910,11 +910,13 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L - Label done; - move_op(opr2, result, type, lir_patch_none, NULL, - false, // pop_fpu_stack -+ false, // unaligned - false); // wide - __ j(done); - __ bind(label); - move_op(opr1, result, type, lir_patch_none, NULL, - false, // pop_fpu_stack -+ false, // unaligned - false); // wide - __ bind(done); - } -@@ -1866,7 +1868,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* arg - - void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { - if (dest->is_address() || src->is_address()) { -- move_op(src, dest, type, lir_patch_none, info, /* pop_fpu_stack */ false, /* wide */ false); -+ move_op(src, dest, type, lir_patch_none, info, /* pop_fpu_stack */ false, /*unaligned*/ false, /* wide */ false); - } else { - ShouldNotReachHere(); - } -diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -index d724876ec3a..bc847388f68 100644 ---- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -340,7 +340,7 @@ void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrier - Register pre_val_reg = stub->pre_val()->as_register(); - - if (stub->do_load()) { -- ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */); -+ ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */, false /*unaligned*/); - } - __ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true); - ce->store_parameter(stub->pre_val()->as_register(), 0); - -From 5f15abe61c700cbf59805530c52e8e558354d552 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:54:05 +0800 -Subject: [PATCH 068/140] Revert JDK-8264805: Remove the experimental - Ahead-of-Time Compiler - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp | 1 + - src/hotspot/cpu/riscv/compiledIC_riscv.cpp | 4 ++-- - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp -index 051328c3a8a..5c81f1c704c 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp -@@ -73,6 +73,7 @@ friend class ArrayCopyStub; - // CompiledStaticCall::to_interp_stub_size() (14) + CompiledStaticCall::to_trampoline_stub_size() (1 + 3 + address) - _call_stub_size = 14 * NativeInstruction::instruction_size + - (NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size), -+ _call_aot_stub_size = 0, - // See emit_exception_handler for detail - // verify_not_null_oop + far_call + should_not_reach_here + invalidate_registers(DEBUG_ONLY) - _exception_handler_size = DEBUG_ONLY(584) NOT_DEBUG(548), // or smaller -diff --git a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -index 1cfc92b28fa..a29e5be9dbb 100644 ---- a/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -+++ b/src/hotspot/cpu/riscv/compiledIC_riscv.cpp -@@ -86,7 +86,7 @@ int CompiledStaticCall::reloc_to_interp_stub() { - } - - void CompiledDirectStaticCall::set_to_interpreted(const methodHandle& callee, address entry) { -- address stub = find_stub(); -+ address stub = find_stub(false /* is_aot */); - guarantee(stub != NULL, "stub not found"); - - if (TraceICs) { -@@ -138,7 +138,7 @@ void CompiledDirectStaticCall::verify() { - _call->verify_alignment(); - - // Verify stub. -- address stub = find_stub(); -+ address stub = find_stub(false /* is_aot */); - assert(stub != NULL, "no stub found for static call"); - // Creation also verifies the object. - NativeMovConstReg* method_holder - -From 4cfd20c7d163188a1a4e63ffaa19708e15be9d96 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 17:59:45 +0800 -Subject: [PATCH 069/140] Revert JDK-8277417: C1 LIR instruction for load-klass - ---- - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 30 ++++++++----------- - 1 file changed, 12 insertions(+), 18 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index e29c0df5f8b..49653d04d81 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -840,7 +840,14 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch - __ ld(dest->as_register(), as_Address(from_addr)); - break; - case T_ADDRESS: -- __ ld(dest->as_register(), as_Address(from_addr)); -+ // FIXME: OMG this is a horrible kludge. Any offset from an -+ // address that matches klass_offset_in_bytes() will be loaded -+ // as a word, not a long. -+ if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { -+ __ lwu(dest->as_register(), as_Address(from_addr)); -+ } else { -+ __ ld(dest->as_register(), as_Address(from_addr)); -+ } - break; - case T_INT: - __ lw(dest->as_register(), as_Address(from_addr)); -@@ -869,6 +876,10 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch - __ decode_heap_oop(dest->as_register()); - } - __ verify_oop(dest->as_register()); -+ } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { -+ if (UseCompressedClassPointers) { -+ __ decode_klass_not_null(dest->as_register()); -+ } - } - } - -@@ -1531,23 +1542,6 @@ void LIR_Assembler::emit_lock(LIR_OpLock* op) { - __ bind(*op->stub()->continuation()); - } - --void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) { -- Register obj = op->obj()->as_pointer_register(); -- Register result = op->result_opr()->as_pointer_register(); -- -- CodeEmitInfo* info = op->info(); -- if (info != NULL) { -- add_debug_info_for_null_check_here(info); -- } -- -- if (UseCompressedClassPointers) { -- __ lwu(result, Address(obj, oopDesc::klass_offset_in_bytes())); -- __ decode_klass_not_null(result); -- } else { -- __ ld(result, Address(obj, oopDesc::klass_offset_in_bytes())); -- } --} -- - void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { - ciMethod* method = op->profiled_method(); - int bci = op->profiled_bci(); - -From eb4de6fc8f9b6192d16343382ebbe4035ce71702 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:09:31 +0800 -Subject: [PATCH 070/140] Revert JDK-8245957: Remove unused LIR_OpBranch::type - after SPARC port removal - ---- - src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index a9345158749..2aba4f4974f 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -393,7 +393,7 @@ void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { - if (need_zero_check) { - CodeEmitInfo* info = state_for(x); - __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0)); -- __ branch(lir_cond_equal, new DivByZeroStub(info)); -+ __ branch(lir_cond_equal, T_LONG, new DivByZeroStub(info)); - } - - rlock_result(x); -@@ -467,7 +467,7 @@ void LIRGenerator::do_ArithmeticOp_Int(ArithmeticOp* x) { - if (need_zero_check) { - CodeEmitInfo* info = state_for(x); - __ cmp(lir_cond_equal, right_arg->result(), LIR_OprFact::longConst(0)); -- __ branch(lir_cond_equal, new DivByZeroStub(info)); -+ __ branch(lir_cond_equal, T_INT, new DivByZeroStub(info)); - } - - LIR_Opr ill = LIR_OprFact::illegalOpr; -@@ -1055,9 +1055,9 @@ void LIRGenerator::do_If(If* x) { - profile_branch(x, cond); - move_to_phi(x->state()); - if (x->x()->type()->is_float_kind()) { -- __ branch(lir_cond(cond), x->tsux(), x->usux()); -+ __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux()); - } else { -- __ branch(lir_cond(cond), x->tsux()); -+ __ branch(lir_cond(cond), right->type(), x->tsux()); - } - assert(x->default_sux() == x->fsux(), "wrong destination above"); - __ jump(x->default_sux()); - -From d34f25c618982d3ac79e6ab2a47b3a199434d01b Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:14:10 +0800 -Subject: [PATCH 071/140] Revert JDK-8266950: Remove vestigial support for - non-strict floating-point execution - ---- - src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp | 4 ++++ - src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp | 7 ++++++- - 2 files changed, 10 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -index 65d0eda62ef..2a99d49c94b 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp -@@ -238,7 +238,9 @@ void LIR_Assembler::arith_op_single_fpu(LIR_Code code, LIR_Opr left, LIR_Opr rig - switch (code) { - case lir_add: __ fadd_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; - case lir_sub: __ fsub_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; -+ case lir_mul_strictfp: // fall through - case lir_mul: __ fmul_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; -+ case lir_div_strictfp: // fall through - case lir_div: __ fdiv_s(dest->as_float_reg(), left->as_float_reg(), right->as_float_reg()); break; - default: - ShouldNotReachHere(); -@@ -251,7 +253,9 @@ void LIR_Assembler::arith_op_double_fpu(LIR_Code code, LIR_Opr left, LIR_Opr rig - switch (code) { - case lir_add: __ fadd_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; - case lir_sub: __ fsub_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; -+ case lir_mul_strictfp: // fall through - case lir_mul: __ fmul_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; -+ case lir_div_strictfp: // fall through - case lir_div: __ fdiv_d(dest->as_double_reg(), left->as_double_reg(), right->as_double_reg()); break; - default: - ShouldNotReachHere(); -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index 2aba4f4974f..21ae066e9ab 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -360,7 +360,12 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { - right.load_item(); - - LIR_Opr reg = rlock(x); -- arithmetic_op_fpu(x->op(), reg, left.result(), right.result()); -+ LIR_Opr tmp = LIR_OprFact::illegalOpr; -+ if (x->is_strictfp() && (x->op() == Bytecodes::_dmul || x->op() == Bytecodes::_ddiv)) { -+ tmp = new_register(T_DOUBLE); -+ } -+ -+ arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), x->is_strictfp()); - - set_result(x, round_item(reg)); - } - -From 02c0a84d52417d4aeddbdd10c07df446ee45c5de Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:19:51 +0800 -Subject: [PATCH 072/140] Revert JDK-8276217: Harmonize StrictMath intrinsics - handling - ---- - src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp | 6 ++---- - 1 file changed, 2 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index 21ae066e9ab..f9242251491 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -651,16 +651,14 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { - do_LibmIntrinsic(x); - break; - case vmIntrinsics::_dabs: // fall through -- case vmIntrinsics::_dsqrt: // fall through -- case vmIntrinsics::_dsqrt_strict: { -+ case vmIntrinsics::_dsqrt: { - assert(x->number_of_arguments() == 1, "wrong type"); - LIRItem value(x->argument_at(0), this); - value.load_item(); - LIR_Opr dst = rlock_result(x); - - switch (x->id()) { -- case vmIntrinsics::_dsqrt: // fall through -- case vmIntrinsics::_dsqrt_strict: { -+ case vmIntrinsics::_dsqrt: { - __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr); - break; - } - -From 8dbace163d42cbb41ff49463b34f8971437fe82f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:35:08 +0800 -Subject: [PATCH 073/140] Revert JDK-8276209: Some call sites doesn't pass the - parameter 'size' to SharedRuntime::dtrace_object_alloc(_base) - ---- - src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -index fc88d5c180e..329df2e1ca7 100644 ---- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp -@@ -1186,7 +1186,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { - StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); - save_live_registers(sasm); - -- __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), c_rarg0); -+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), c_rarg0); - - restore_live_registers(sasm); - } -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index 2a92fb9dd49..ddc9498dddc 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -3577,7 +3577,7 @@ void TemplateTable::_new() { - SkipIfEqual skip(_masm, &DTraceAllocProbes, false); - // Trigger dtrace event for fastpath - __ push(atos); // save the return value -- __ call_VM_leaf(CAST_FROM_FN_PTR(address, static_cast(SharedRuntime::dtrace_object_alloc)), x10); -+ __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), x10); - __ pop(atos); // restore the return value - } - __ j(done); - -From 8930b6049a5b6e31ec9409c167b0e58d24cf6821 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:38:51 +0800 -Subject: [PATCH 074/140] Revert JDK-8229838: Rename markOop files to markWord - ---- - src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp | 1 - - src/hotspot/cpu/riscv/frame_riscv.cpp | 1 - - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 1 - - 3 files changed, 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index e486f41948e..44ceccd8bd1 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -33,7 +33,6 @@ - #include "gc/shared/collectedHeap.hpp" - #include "interpreter/interpreter.hpp" - #include "oops/arrayOop.hpp" --#include "oops/markWord.hpp" - #include "runtime/basicLock.hpp" - #include "runtime/biasedLocking.hpp" - #include "runtime/os.hpp" -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 13c482b610a..050595389e9 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -29,7 +29,6 @@ - #include "interpreter/interpreter.hpp" - #include "memory/resourceArea.hpp" - #include "memory/universe.hpp" --#include "oops/markWord.hpp" - #include "oops/method.hpp" - #include "oops/oop.inline.hpp" - #include "prims/methodHandles.hpp" -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 2fc0b00e2cb..006fe49b155 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -33,7 +33,6 @@ - #include "interpreter/interpreterRuntime.hpp" - #include "logging/log.hpp" - #include "oops/arrayOop.hpp" --#include "oops/markWord.hpp" - #include "oops/method.hpp" - #include "oops/methodData.hpp" - #include "prims/jvmtiExport.hpp" - -From f11c5a2beca94c8248c30899fef90947d478e10c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:42:33 +0800 -Subject: [PATCH 075/140] Revert JDK-8235673: [C1, C2] Split inlining control - flags - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index fe46f7b21c8..fd25f8f9afd 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -42,6 +42,7 @@ define_pd_global(bool, TieredCompilation, false); - define_pd_global(intx, CompileThreshold, 1500 ); - - define_pd_global(intx, OnStackReplacePercentage, 933 ); -+define_pd_global(intx, FreqInlineSize, 325 ); - define_pd_global(intx, NewSizeThreadIncrease, 4*K ); - define_pd_global(intx, InitialCodeCacheSize, 160*K); - define_pd_global(intx, ReservedCodeCacheSize, 32*M ); - -From 6908dc58f2c66ca6a5adf4444a7ec2a91a80b9c8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:45:00 +0800 -Subject: [PATCH 076/140] Revert JDK-8262074: Consolidate the default value of - MetaspaceSize - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 1 + - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 3 +++ - 2 files changed, 4 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index fd25f8f9afd..1c55a23eecf 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -53,6 +53,7 @@ define_pd_global(bool, ProfileInterpreter, false); - define_pd_global(intx, CodeCacheExpansionSize, 32*K ); - define_pd_global(uintx, CodeCacheMinBlockLength, 1); - define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); -+define_pd_global(uintx, MetaspaceSize, 12*M ); - define_pd_global(bool, NeverActAsServerClassMachine, true ); - define_pd_global(uint64_t, MaxRAM, 1ULL*G); - define_pd_global(bool, CICompileOSR, true ); -diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -index 53a41665f4b..d9e5fcc1bb0 100644 ---- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -@@ -75,6 +75,9 @@ define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); - define_pd_global(uintx, CodeCacheMinBlockLength, 6); - define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); - -+// Heap related flags -+define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(16*M)); -+ - // Ergonomics related flags - define_pd_global(bool, NeverActAsServerClassMachine, false); - - -From a3e991b37781d90c822471b54ace915622bee0da Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:48:15 +0800 -Subject: [PATCH 077/140] Revert JDK-8246023: Obsolete LIRFillDelaySlot - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index 1c55a23eecf..bd8d039de03 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -60,6 +60,7 @@ define_pd_global(bool, CICompileOSR, true ); - #endif // !COMPILER2 - define_pd_global(bool, UseTypeProfile, false); - -+define_pd_global(bool, LIRFillDelaySlots, false); - define_pd_global(bool, OptimizeSinglePrecision, true ); - define_pd_global(bool, CSEArrayLength, false); - define_pd_global(bool, TwoOperandLIRForm, false); - -From 9f6082ae9810e6a26c6803cb37cce62297d15a74 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:50:27 +0800 -Subject: [PATCH 078/140] Revert JDK-8136414: Large performance penalty - declaring a method strictfp on strict-only platforms - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index bd8d039de03..16a87b7aced 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -59,6 +59,7 @@ define_pd_global(uint64_t, MaxRAM, 1ULL*G); - define_pd_global(bool, CICompileOSR, true ); - #endif // !COMPILER2 - define_pd_global(bool, UseTypeProfile, false); -+define_pd_global(bool, RoundFPResults, true ); - - define_pd_global(bool, LIRFillDelaySlots, false); - define_pd_global(bool, OptimizeSinglePrecision, true ); - -From fbf03fc61be068f7f7c8ca1ab3854cc05519c5a3 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Tue, 25 Apr 2023 18:58:36 +0800 -Subject: [PATCH 079/140] Revert JDK-8251462: Simplify compilation policy - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 4 +- - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 2 +- - src/hotspot/cpu/riscv/globals_riscv.hpp | 2 +- - .../templateInterpreterGenerator_riscv.cpp | 114 +++++++++--- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 176 ++++++++++++------ - 5 files changed, 210 insertions(+), 88 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index 16a87b7aced..8f2f4e0e81d 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -32,7 +32,7 @@ - // Sets the default values for platform dependent flags used by the client compiler. - // (see c1_globals.hpp) - --#ifndef COMPILER2 -+#ifndef TIERED - define_pd_global(bool, BackgroundCompilation, true ); - define_pd_global(bool, InlineIntrinsics, true ); - define_pd_global(bool, PreferInterpreterNativeStubs, false); -@@ -57,7 +57,7 @@ define_pd_global(uintx, MetaspaceSize, 12*M ); - define_pd_global(bool, NeverActAsServerClassMachine, true ); - define_pd_global(uint64_t, MaxRAM, 1ULL*G); - define_pd_global(bool, CICompileOSR, true ); --#endif // !COMPILER2 -+#endif // !TIERED - define_pd_global(bool, UseTypeProfile, false); - define_pd_global(bool, RoundFPResults, true ); - -diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -index d9e5fcc1bb0..6c301cdae04 100644 ---- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -@@ -39,7 +39,7 @@ define_pd_global(bool, PreferInterpreterNativeStubs, false); - define_pd_global(bool, ProfileTraps, true); - define_pd_global(bool, UseOnStackReplacement, true); - define_pd_global(bool, ProfileInterpreter, true); --define_pd_global(bool, TieredCompilation, COMPILER1_PRESENT(true) NOT_COMPILER1(false)); -+define_pd_global(bool, TieredCompilation, trueInTiered); - define_pd_global(intx, CompileThreshold, 10000); - - define_pd_global(intx, OnStackReplacePercentage, 140); -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index 50bbb6a77b8..b78f258a764 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -36,7 +36,7 @@ define_pd_global(bool, ImplicitNullChecks, true); // Generate code for im - define_pd_global(bool, TrapBasedNullChecks, false); - define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast - --define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. -+define_pd_global(uintx, CodeCacheSegmentSize, 64 TIERED_ONLY(+64)); // Tiered compilation has large code-entry alignment. - define_pd_global(intx, CodeEntryAlignment, 64); - define_pd_global(intx, OptoLoopAlignment, 16); - -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index a10677bf650..8aea4eca048 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -556,31 +556,81 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, - // - // xmethod: method - // --void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow) { -+void TemplateInterpreterGenerator::generate_counter_incr( -+ Label* overflow, -+ Label* profile_method, -+ Label* profile_method_continue) { - Label done; - // Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not. -- int increment = InvocationCounter::count_increment; -- Label no_mdo; -- if (ProfileInterpreter) { -- // Are we profiling? -- __ ld(x10, Address(xmethod, Method::method_data_offset())); -- __ beqz(x10, no_mdo); -- // Increment counter in the MDO -- const Address mdo_invocation_counter(x10, in_bytes(MethodData::invocation_counter_offset()) + -- in_bytes(InvocationCounter::counter_offset())); -- const Address mask(x10, in_bytes(MethodData::invoke_mask_offset())); -- __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, t0, t1, false, overflow); -- __ j(done); -+ if (TieredCompilation) { -+ int increment = InvocationCounter::count_increment; -+ Label no_mdo; -+ if (ProfileInterpreter) { -+ // Are we profiling? -+ __ ld(x10, Address(xmethod, Method::method_data_offset())); -+ __ beqz(x10, no_mdo); -+ // Increment counter in the MDO -+ const Address mdo_invocation_counter(x10, in_bytes(MethodData::invocation_counter_offset()) + -+ in_bytes(InvocationCounter::counter_offset())); -+ const Address mask(x10, in_bytes(MethodData::invoke_mask_offset())); -+ __ increment_mask_and_jump(mdo_invocation_counter, increment, mask, t0, t1, false, overflow); -+ __ j(done); -+ } -+ __ bind(no_mdo); -+ // Increment counter in MethodCounters -+ const Address invocation_counter(t1, -+ MethodCounters::invocation_counter_offset() + -+ InvocationCounter::counter_offset()); -+ __ get_method_counters(xmethod, t1, done); -+ const Address mask(t1, in_bytes(MethodCounters::invoke_mask_offset())); -+ __ increment_mask_and_jump(invocation_counter, increment, mask, t0, x11, false, overflow); -+ __ bind(done); -+ } else { // not TieredCompilation -+ const Address backedge_counter(t1, -+ MethodCounters::backedge_counter_offset() + -+ InvocationCounter::counter_offset()); -+ const Address invocation_counter(t1, -+ MethodCounters::invocation_counter_offset() + -+ InvocationCounter::counter_offset()); -+ -+ __ get_method_counters(xmethod, t1, done); -+ -+ if (ProfileInterpreter) { // %%% Merge this into MethodData* -+ __ lwu(x11, Address(t1, MethodCounters::interpreter_invocation_counter_offset())); -+ __ addw(x11, x11, 1); -+ __ sw(x11, Address(t1, MethodCounters::interpreter_invocation_counter_offset())); -+ } -+ // Update standard invocation counters -+ __ lwu(x11, invocation_counter); -+ __ lwu(x10, backedge_counter); -+ -+ __ addw(x11, x11, InvocationCounter::count_increment); -+ __ andi(x10, x10, InvocationCounter::count_mask_value); -+ -+ __ sw(x11, invocation_counter); -+ __ addw(x10, x10, x11); // add both counters -+ -+ // profile_method is non-null only for interpreted method so -+ // profile_method != NULL == !native_call -+ -+ if (ProfileInterpreter && profile_method != NULL) { -+ // Test to see if we should create a method data oop -+ __ ld(t1, Address(xmethod, Method::method_counters_offset())); -+ __ lwu(t1, Address(t1, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); -+ __ blt(x10, t1, *profile_method_continue); -+ -+ // if no method data exists, go to profile_method -+ __ test_method_data_pointer(t1, *profile_method); -+ } -+ -+ { -+ __ ld(t1, Address(xmethod, Method::method_counters_offset())); -+ __ lwu(t1, Address(t1, in_bytes(MethodCounters::interpreter_invocation_limit_offset()))); -+ __ bltu(x10, t1, done); -+ __ j(*overflow); -+ } -+ __ bind(done); - } -- __ bind(no_mdo); -- // Increment counter in MethodCounters -- const Address invocation_counter(t1, -- MethodCounters::invocation_counter_offset() + -- InvocationCounter::counter_offset()); -- __ get_method_counters(xmethod, t1, done); -- const Address mask(t1, in_bytes(MethodCounters::invoke_mask_offset())); -- __ increment_mask_and_jump(invocation_counter, increment, mask, t0, x11, false, overflow); -- __ bind(done); - } - - void TemplateInterpreterGenerator::generate_counter_overflow(Label& do_continue) { -@@ -977,7 +1027,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { - // increment invocation count & check for overflow - Label invocation_counter_overflow; - if (inc_counter) { -- generate_counter_incr(&invocation_counter_overflow); -+ generate_counter_incr(&invocation_counter_overflow, NULL, NULL); - } - - Label continue_after_compile; -@@ -1389,8 +1439,15 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { - - // increment invocation count & check for overflow - Label invocation_counter_overflow; -+ Label profile_method; -+ Label profile_method_continue; - if (inc_counter) { -- generate_counter_incr(&invocation_counter_overflow); -+ generate_counter_incr(&invocation_counter_overflow, -+ &profile_method, -+ &profile_method_continue); -+ if (ProfileInterpreter) { -+ __ bind(profile_method_continue); -+ } - } - - Label continue_after_compile; -@@ -1427,6 +1484,15 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { - - // invocation counter overflow - if (inc_counter) { -+ if (ProfileInterpreter) { -+ // We have decided to profile this method in the interpreter -+ __ bind(profile_method); -+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); -+ __ set_method_data_pointer_for_bcp(); -+ // don't think we need this -+ __ get_method(x11); -+ __ j(profile_method_continue); -+ } - // Handle overflow of counter and compile method - __ bind(invocation_counter_overflow); - generate_counter_overflow(continue_after_compile); -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index ddc9498dddc..bb20f228447 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -1745,6 +1745,7 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) - assert(UseLoopCounter || !UseOnStackReplacement, - "on-stack-replacement requires loop counters"); - Label backedge_counter_overflow; -+ Label profile_method; - Label dispatch; - if (UseLoopCounter) { - // increment backedge counter for backward branches -@@ -1769,31 +1770,75 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) - __ beqz(t0, dispatch); // No MethodCounters allocated, OutOfMemory - __ bind(has_counters); - -- Label no_mdo; -- int increment = InvocationCounter::count_increment; -- if (ProfileInterpreter) { -- // Are we profiling? -- __ ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); -- __ beqz(x11, no_mdo); -- // Increment the MDO backedge counter -- const Address mdo_backedge_counter(x11, in_bytes(MethodData::backedge_counter_offset()) + -- in_bytes(InvocationCounter::counter_offset())); -- const Address mask(x11, in_bytes(MethodData::backedge_mask_offset())); -- __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, -- x10, t0, false, -+ if (TieredCompilation) { -+ Label no_mdo; -+ int increment = InvocationCounter::count_increment; -+ if (ProfileInterpreter) { -+ // Are we profiling? -+ __ ld(x11, Address(xmethod, in_bytes(Method::method_data_offset()))); -+ __ beqz(x11, no_mdo); -+ // Increment the MDO backedge counter -+ const Address mdo_backedge_counter(x11, in_bytes(MethodData::backedge_counter_offset()) + -+ in_bytes(InvocationCounter::counter_offset())); -+ const Address mask(x11, in_bytes(MethodData::backedge_mask_offset())); -+ __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, -+ x10, t0, false, -+ UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); -+ __ j(dispatch); -+ } -+ __ bind(no_mdo); -+ // Increment backedge counter in MethodCounters* -+ __ ld(t0, Address(xmethod, Method::method_counters_offset())); -+ const Address mask(t0, in_bytes(MethodCounters::backedge_mask_offset())); -+ __ increment_mask_and_jump(Address(t0, be_offset), increment, mask, -+ x10, t1, false, - UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); -- __ j(dispatch); -+ } else { // not TieredCompilation -+ // increment counter -+ __ ld(t1, Address(xmethod, Method::method_counters_offset())); -+ __ lwu(x10, Address(t1, be_offset)); // load backedge counter -+ __ addw(t0, x10, InvocationCounter::count_increment); // increment counter -+ __ sw(t0, Address(t1, be_offset)); // store counter -+ -+ __ lwu(x10, Address(t1, inv_offset)); // load invocation counter -+ __ andi(x10, x10, (unsigned)InvocationCounter::count_mask_value, x13); // and the status bits -+ __ addw(x10, x10, t0); // add both counters -+ -+ if (ProfileInterpreter) { -+ // Test to see if we should create a method data oop -+ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_profile_limit_offset()))); -+ __ blt(x10, t0, dispatch); -+ -+ // if no method data exists, go to profile method -+ __ test_method_data_pointer(x10, profile_method); -+ -+ if (UseOnStackReplacement) { -+ // check for overflow against x11 which is the MDO taken count -+ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); -+ __ bltu(x11, t0, dispatch); // Intel == Assembler::below, lo:unsigned lower -+ -+ // When ProfileInterpreter is on, the backedge_count comes -+ // from the MethodData*, which value does not get reset on -+ // the call to frequency_counter_overflow(). To avoid -+ // excessive calls to the overflow routine while the method is -+ // being compiled, add a second test to make sure the overflow -+ // function is called only once every overflow_frequency. -+ const int overflow_frequency = 1024; -+ __ andi(x11, x11, overflow_frequency - 1); -+ __ beqz(x11, backedge_counter_overflow); -+ -+ } -+ } else { -+ if (UseOnStackReplacement) { -+ // check for overflow against x10, which is the sum of the -+ // counters -+ __ lwu(t0, Address(t1, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()))); -+ __ bgeu(x10, t0, backedge_counter_overflow); // Intel == Assembler::aboveEqual -+ } -+ } - } -- __ bind(no_mdo); -- // Increment backedge counter in MethodCounters* -- __ ld(t0, Address(xmethod, Method::method_counters_offset())); -- const Address mask(t0, in_bytes(MethodCounters::backedge_mask_offset())); -- __ increment_mask_and_jump(Address(t0, be_offset), increment, mask, -- x10, t1, false, -- UseOnStackReplacement ? &backedge_counter_overflow : &dispatch); - __ bind(dispatch); - } -- - // Pre-load the next target bytecode into t0 - __ load_unsigned_byte(t0, Address(xbcp, 0)); - -@@ -1802,52 +1847,63 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) - // xbcp: target bcp - __ dispatch_only(vtos, /*generate_poll*/true); - -- if (UseLoopCounter && UseOnStackReplacement) { -- // invocation counter overflow -- __ bind(backedge_counter_overflow); -- __ neg(x12, x12); -- __ add(x12, x12, xbcp); // branch xbcp -- // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) -- __ call_VM(noreg, -- CAST_FROM_FN_PTR(address, -- InterpreterRuntime::frequency_counter_overflow), -- x12); -- __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode -- -- // x10: osr nmethod (osr ok) or NULL (osr not possible) -- // w11: target bytecode -- // x12: temporary -- __ beqz(x10, dispatch); // test result -- no osr if null -- // nmethod may have been invalidated (VM may block upon call_VM return) -- __ lbu(x12, Address(x10, nmethod::state_offset())); -- if (nmethod::in_use != 0) { -- __ sub(x12, x12, nmethod::in_use); -+ if (UseLoopCounter) { -+ if (ProfileInterpreter && !TieredCompilation) { -+ // Out-of-line code to allocate method data oop. -+ __ bind(profile_method); -+ __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method)); -+ __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode -+ __ set_method_data_pointer_for_bcp(); -+ __ j(dispatch); - } -- __ bnez(x12, dispatch); - -- // We have the address of an on stack replacement routine in x10 -- // We need to prepare to execute the OSR method. First we must -- // migrate the locals and monitors off of the stack. -+ if (UseOnStackReplacement) { -+ // invocation counter overflow -+ __ bind(backedge_counter_overflow); -+ __ neg(x12, x12); -+ __ add(x12, x12, xbcp); // branch xbcp -+ // IcoResult frequency_counter_overflow([JavaThread*], address branch_bcp) -+ __ call_VM(noreg, -+ CAST_FROM_FN_PTR(address, -+ InterpreterRuntime::frequency_counter_overflow), -+ x12); -+ __ load_unsigned_byte(x11, Address(xbcp, 0)); // restore target bytecode -+ -+ // x10: osr nmethod (osr ok) or NULL (osr not possible) -+ // w11: target bytecode -+ // x12: temporary -+ __ beqz(x10, dispatch); // test result -- no osr if null -+ // nmethod may have been invalidated (VM may block upon call_VM return) -+ __ lbu(x12, Address(x10, nmethod::state_offset())); -+ if (nmethod::in_use != 0) { -+ __ sub(x12, x12, nmethod::in_use); -+ } -+ __ bnez(x12, dispatch); -+ -+ // We have the address of an on stack replacement routine in x10 -+ // We need to prepare to execute the OSR method. First we must -+ // migrate the locals and monitors off of the stack. - -- __ mv(x9, x10); // save the nmethod -+ __ mv(x9, x10); // save the nmethod - -- call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); -+ call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin)); - -- // x10 is OSR buffer, move it to expected parameter location -- __ mv(j_rarg0, x10); -+ // x10 is OSR buffer, move it to expected parameter location -+ __ mv(j_rarg0, x10); - -- // remove activation -- // get sender esp -- __ ld(esp, -- Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); -- // remove frame anchor -- __ leave(); -- // Ensure compiled code always sees stack at proper alignment -- __ andi(sp, esp, -16); -+ // remove activation -+ // get sender esp -+ __ ld(esp, -+ Address(fp, frame::interpreter_frame_sender_sp_offset * wordSize)); -+ // remove frame anchor -+ __ leave(); -+ // Ensure compiled code always sees stack at proper alignment -+ __ andi(sp, esp, -16); - -- // and begin the OSR nmethod -- __ ld(t0, Address(x9, nmethod::osr_entry_point_offset())); -- __ jr(t0); -+ // and begin the OSR nmethod -+ __ ld(t0, Address(x9, nmethod::osr_entry_point_offset())); -+ __ jr(t0); -+ } - } - } - - -From b1f3fd0510681324d70028443a3532d6084be504 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 27 Apr 2023 11:37:05 +0800 -Subject: [PATCH 080/140] Revert JDK-8250902: Implement MD5 Intrinsics on x86 - ---- - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 5 ---- - ...nericTestCaseForUnsupportedRISCV64CPU.java | 30 +++++++++---------- - 2 files changed, 15 insertions(+), 20 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index c0491d23fa6..d4b79162d84 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -97,11 +97,6 @@ void VM_Version::initialize() { - FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); - } - -- if (UseMD5Intrinsics) { -- warning("MD5 intrinsics are not available on this CPU."); -- FLAG_SET_DEFAULT(UseMD5Intrinsics, false); -- } -- - if (UseRVV) { - if (!(_features & CPU_V)) { - warning("RVV is not supported on this CPU"); -diff --git a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java -index 2ecfec07a4c..8566d57c391 100644 ---- a/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java -+++ b/test/hotspot/jtreg/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedRISCV64CPU.java -@@ -24,7 +24,7 @@ - - package compiler.intrinsics.sha.cli.testcases; - --import compiler.intrinsics.sha.cli.DigestOptionsBase; -+import compiler.intrinsics.sha.cli.SHAOptionsBase; - import jdk.test.lib.process.ExitCode; - import jdk.test.lib.Platform; - import jdk.test.lib.cli.CommandLineOptionTest; -@@ -36,7 +36,7 @@ - * which don't support instruction required by the tested option. - */ - public class GenericTestCaseForUnsupportedRISCV64CPU extends -- DigestOptionsBase.TestCase { -+ SHAOptionsBase.TestCase { - - final private boolean checkUseSHA; - -@@ -46,7 +46,7 @@ public GenericTestCaseForUnsupportedRISCV64CPU(String optionName) { - - public GenericTestCaseForUnsupportedRISCV64CPU(String optionName, boolean checkUseSHA) { - super(optionName, new AndPredicate(Platform::isRISCV64, -- new NotPredicate(DigestOptionsBase.getPredicateForOption( -+ new NotPredicate(SHAOptionsBase.getPredicateForOption( - optionName)))); - - this.checkUseSHA = checkUseSHA; -@@ -58,27 +58,27 @@ protected void verifyWarnings() throws Throwable { - + "option '-XX:-%s' without any warnings", optionName); - //Verify that option could be disabled without any warnings. - CommandLineOptionTest.verifySameJVMStartup(null, new String[] { -- DigestOptionsBase.getWarningForUnsupportedCPU(optionName) -+ SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, shouldPassMessage, shouldPassMessage, ExitCode.OK, -- DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -+ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.prepareBooleanFlag(optionName, false)); - - if (checkUseSHA) { - shouldPassMessage = String.format("If JVM is started with '-XX:-" - + "%s' '-XX:+%s', output should contain warning.", -- DigestOptionsBase.USE_SHA_OPTION, optionName); -+ SHAOptionsBase.USE_SHA_OPTION, optionName); - - // Verify that when the tested option is enabled, then - // a warning will occur in VM output if UseSHA is disabled. -- if (!optionName.equals(DigestOptionsBase.USE_SHA_OPTION)) { -+ if (!optionName.equals(SHAOptionsBase.USE_SHA_OPTION)) { - CommandLineOptionTest.verifySameJVMStartup( -- new String[] { DigestOptionsBase.getWarningForUnsupportedCPU(optionName) }, -+ new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) }, - null, - shouldPassMessage, - shouldPassMessage, - ExitCode.OK, -- DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -- CommandLineOptionTest.prepareBooleanFlag(DigestOptionsBase.USE_SHA_OPTION, false), -+ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -+ CommandLineOptionTest.prepareBooleanFlag(SHAOptionsBase.USE_SHA_OPTION, false), - CommandLineOptionTest.prepareBooleanFlag(optionName, true)); - } - } -@@ -90,7 +90,7 @@ protected void verifyOptionValues() throws Throwable { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", - String.format("Option '%s' should be disabled by default", - optionName), -- DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS); -+ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS); - - if (checkUseSHA) { - // Verify that option is disabled even if it was explicitly enabled -@@ -98,7 +98,7 @@ protected void verifyOptionValues() throws Throwable { - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", - String.format("Option '%s' should be off on unsupported " - + "RISCV64CPU even if set to true directly", optionName), -- DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -+ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.prepareBooleanFlag(optionName, true)); - - // Verify that option is disabled when +UseSHA was passed to JVM. -@@ -106,10 +106,10 @@ protected void verifyOptionValues() throws Throwable { - String.format("Option '%s' should be off on unsupported " - + "RISCV64CPU even if %s flag set to JVM", - optionName, CommandLineOptionTest.prepareBooleanFlag( -- DigestOptionsBase.USE_SHA_OPTION, true)), -- DigestOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, -+ SHAOptionsBase.USE_SHA_OPTION, true)), -+ SHAOptionsBase.UNLOCK_DIAGNOSTIC_VM_OPTIONS, - CommandLineOptionTest.prepareBooleanFlag( -- DigestOptionsBase.USE_SHA_OPTION, true)); -+ SHAOptionsBase.USE_SHA_OPTION, true)); - } - } - } - -From b5e96cb7663b2def3a064b9aede7209fb0c5eeda Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 27 Apr 2023 15:41:48 +0800 -Subject: [PATCH 081/140] Revert JDK-8253555: Make ByteSize and WordSize typed - scoped enums - ---- - src/hotspot/cpu/riscv/assembler_riscv.hpp | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp -index 31aeeb9b425..9959ac1d02c 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -195,8 +195,10 @@ class Address { - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } - Address(Register r, unsigned long long o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) { } -+#ifdef ASSERT - Address(Register r, ByteSize disp) -- : Address(r, in_bytes(disp)) { } -+ : _base(r), _index(noreg), _offset(in_bytes(disp)), _mode(base_plus_offset), _target(0) { } -+#endif - Address(address target, RelocationHolder const& rspec) - : _base(noreg), - _index(noreg), - -From 592afab705a4d4c8b2773a0808e47efc2a14517d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 15:18:12 +0800 -Subject: [PATCH 082/140] Revert JDK-8253457: Remove unimplemented register - stack functions - ---- - .../os_cpu/linux_riscv/thread_linux_riscv.hpp | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - -diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -index 61e2cf85b63..313a7b932c3 100644 ---- a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -+++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -@@ -34,15 +34,31 @@ - frame pd_last_frame(); - - public: -+ -+ void set_base_of_stack_pointer(intptr_t* base_sp) { -+ } -+ - static ByteSize last_Java_fp_offset() { - return byte_offset_of(JavaThread, _anchor) + JavaFrameAnchor::last_Java_fp_offset(); - } - -+ intptr_t* base_of_stack_pointer() { -+ return NULL; -+ } -+ void record_base_of_stack_pointer() { -+ } -+ - bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, - bool isInJava); - - bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); - private: - bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); -+public: -+ // These routines are only used on cpu architectures that -+ // have separate register stacks (Itanium). -+ static bool register_stack_overflow() { return false; } -+ static void enable_register_stack_guard() {} -+ static void disable_register_stack_guard() {} - - #endif // OS_CPU_LINUX_RISCV_THREAD_LINUX_RISCV_HPP - -From 28238cf776bd25c9805d9dd686c08fe8d3a1500b Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 15:22:30 +0800 -Subject: [PATCH 083/140] Revert JDK-8253539: Remove unused JavaThread - functions for set_last_Java_fp/pc - ---- - src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp | 3 +++ - src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp | 3 +++ - 2 files changed, 6 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp -index 9a6084afa1d..5a0c9b812fc 100644 ---- a/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp -+++ b/src/hotspot/cpu/riscv/javaFrameAnchor_riscv.hpp -@@ -83,4 +83,7 @@ - - intptr_t* last_Java_fp(void) { return _last_Java_fp; } - -+ // Assert (last_Java_sp == NULL || fp == NULL) -+ void set_last_Java_fp(intptr_t* fp) { OrderAccess::release(); _last_Java_fp = fp; } -+ - #endif // CPU_RISCV_JAVAFRAMEANCHOR_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -index 313a7b932c3..4b91fa855ae 100644 ---- a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -+++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.hpp -@@ -34,6 +34,9 @@ - frame pd_last_frame(); - - public: -+ // Mutators are highly dangerous.... -+ intptr_t* last_Java_fp() { return _anchor.last_Java_fp(); } -+ void set_last_Java_fp(intptr_t* fp) { _anchor.set_last_Java_fp(fp); } - - void set_base_of_stack_pointer(intptr_t* base_sp) { - } - -From f9322bb6235b603eac825c6e6751093ada1e6cfe Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 15:45:56 +0800 -Subject: [PATCH 084/140] Revert JDK-8269853: Prefetch::read should accept - pointer to const - ---- - src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp -index a6432c84ec7..2bd48e09c34 100644 ---- a/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp -+++ b/src/hotspot/os_cpu/linux_riscv/prefetch_linux_riscv.inline.hpp -@@ -29,7 +29,7 @@ - #include "runtime/prefetch.hpp" - - --inline void Prefetch::read (const void *loc, intx interval) { -+inline void Prefetch::read (void *loc, intx interval) { - } - - inline void Prefetch::write(void *loc, intx interval) { - -From aa6f7320d8d849b8e47b6e77a20257e3d99fd14f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 16:14:55 +0800 -Subject: [PATCH 085/140] Revert: JDK-8254231: Implementation of Foreign Linker - API (Incubator) JDK-8264774: Implementation of Foreign Function and Memory - API (Incubator) - ---- - .../cpu/riscv/foreign_globals_riscv.cpp | 44 ------------------- - .../cpu/riscv/foreign_globals_riscv.hpp | 32 -------------- - src/hotspot/cpu/riscv/frame_riscv.cpp | 15 ------- - src/hotspot/cpu/riscv/methodHandles_riscv.cpp | 12 +---- - src/hotspot/cpu/riscv/riscv.ad | 5 --- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 10 +---- - .../riscv/universalNativeInvoker_riscv.cpp | 33 -------------- - .../cpu/riscv/universalUpcallHandle_riscv.cpp | 42 ------------------ - src/hotspot/cpu/riscv/vmreg_riscv.cpp | 5 --- - 9 files changed, 2 insertions(+), 196 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/foreign_globals_riscv.cpp - delete mode 100644 src/hotspot/cpu/riscv/foreign_globals_riscv.hpp - delete mode 100644 src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp - delete mode 100644 src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp - -diff --git a/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp b/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp -deleted file mode 100644 -index 5c700be9c91..00000000000 ---- a/src/hotspot/cpu/riscv/foreign_globals_riscv.cpp -+++ /dev/null -@@ -1,44 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "prims/foreign_globals.hpp" --#include "utilities/debug.hpp" -- --// Stubbed out, implement later --const ABIDescriptor ForeignGlobals::parse_abi_descriptor_impl(jobject jabi) const { -- Unimplemented(); -- return {}; --} -- --const BufferLayout ForeignGlobals::parse_buffer_layout_impl(jobject jlayout) const { -- Unimplemented(); -- return {}; --} -- --const CallRegs ForeignGlobals::parse_call_regs_impl(jobject jconv) const { -- ShouldNotCallThis(); -- return {}; --} -diff --git a/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp b/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp -deleted file mode 100644 -index 3ac89752c27..00000000000 ---- a/src/hotspot/cpu/riscv/foreign_globals_riscv.hpp -+++ /dev/null -@@ -1,32 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP --#define CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP -- --class ABIDescriptor {}; --class BufferLayout {}; -- --#endif // CPU_RISCV_FOREIGN_GLOBALS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 050595389e9..40ec584b994 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -361,21 +361,6 @@ frame frame::sender_for_entry_frame(RegisterMap* map) const { - return fr; - } - --OptimizedEntryBlob::FrameData* OptimizedEntryBlob::frame_data_for_frame(const frame& frame) const { -- ShouldNotCallThis(); -- return nullptr; --} -- --bool frame::optimized_entry_frame_is_first() const { -- ShouldNotCallThis(); -- return false; --} -- --frame frame::sender_for_optimized_entry_frame(RegisterMap* map) const { -- ShouldNotCallThis(); -- return {}; --} -- - //------------------------------------------------------------------------------ - // frame::verify_deopt_original_pc - // -diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -index 1f7c0c87c21..3bf5cfb16c3 100644 ---- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -181,13 +181,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler* - return NULL; - } - -- // No need in interpreter entry for linkToNative for now. -- // Interpreter calls compiled entry through i2c. -- if (iid == vmIntrinsics::_linkToNative) { -- __ ebreak(); -- return NULL; -- } -- - // x30: sender SP (must preserve; see prepare_to_jump_from_interpreted) - // xmethod: Method* - // x13: argument locator (parameter slot count, added to sp) -@@ -280,10 +273,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, - assert_different_registers(temp1, temp2, temp3, receiver_reg); - assert_different_registers(temp1, temp2, temp3, member_reg); - -- if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { -- if (iid == vmIntrinsics::_linkToNative) { -- assert(for_compiler_entry, "only compiler entry is supported"); -- } -+ if (iid == vmIntrinsics::_invokeBasic) { - // indirect through MH.form.vmentry.vmtarget - jump_to_lambda_form(_masm, receiver_reg, xmethod, temp1, for_compiler_entry); - } else { -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 1667994699f..7ec76e72ff0 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -945,11 +945,6 @@ int MachCallRuntimeNode::ret_addr_offset() { - } - } - --int MachCallNativeNode::ret_addr_offset() { -- Unimplemented(); -- return -1; --} -- - // - // Compute padding required for nodes which need alignment - // -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 411bddd2ace..897dafcc99c 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1037,7 +1037,7 @@ static void gen_special_dispatch(MacroAssembler* masm, - member_arg_pos = method->size_of_parameters() - 1; // trailing MemberName argument - member_reg = x9; // known to be free at this point - has_receiver = MethodHandles::ref_kind_has_receiver(ref_kind); -- } else if (iid == vmIntrinsics::_invokeBasic || iid == vmIntrinsics::_linkToNative) { -+ } else if (iid == vmIntrinsics::_invokeBasic) { - has_receiver = true; - } else { - fatal("unexpected intrinsic id %d", vmIntrinsics::as_int(iid)); -@@ -2566,14 +2566,6 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha - } - - #ifdef COMPILER2 --RuntimeStub* SharedRuntime::make_native_invoker(address call_target, -- int shadow_space_bytes, -- const GrowableArray& input_registers, -- const GrowableArray& output_registers) { -- Unimplemented(); -- return nullptr; --} -- - //------------------------------generate_exception_blob--------------------------- - // creates exception blob at the end - // Using exception blob, this code is jumped from a compiled method. -diff --git a/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp b/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp -deleted file mode 100644 -index 4f50adb05c3..00000000000 ---- a/src/hotspot/cpu/riscv/universalNativeInvoker_riscv.cpp -+++ /dev/null -@@ -1,33 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "prims/universalNativeInvoker.hpp" --#include "utilities/debug.hpp" -- --address ProgrammableInvoker::generate_adapter(jobject jabi, jobject jlayout) { -- Unimplemented(); -- return nullptr; --} -diff --git a/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp b/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp -deleted file mode 100644 -index ce70da72f2e..00000000000 ---- a/src/hotspot/cpu/riscv/universalUpcallHandle_riscv.cpp -+++ /dev/null -@@ -1,42 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * 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 "prims/universalUpcallHandler.hpp" --#include "utilities/debug.hpp" -- --address ProgrammableUpcallHandler::generate_upcall_stub(jobject jrec, jobject jabi, jobject jlayout) { -- Unimplemented(); -- return nullptr; --} -- --address ProgrammableUpcallHandler::generate_optimized_upcall_stub(jobject mh, Method* entry, jobject jabi, jobject jconv) { -- ShouldNotCallThis(); -- return nullptr; --} -- --bool ProgrammableUpcallHandler::supports_optimized_upcalls() { -- return false; --} -diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.cpp b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -index 1f6eff96cba..5d1187c2a27 100644 ---- a/src/hotspot/cpu/riscv/vmreg_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -@@ -49,8 +49,3 @@ void VMRegImpl::set_regName() { - regName[i] = "NON-GPR-FPR"; - } - } -- --VMReg VMRegImpl::vmStorageToVMReg(int type, int index) { -- Unimplemented(); -- return VMRegImpl::Bad(); --} - -From a5889735a97f3712bb649c454dee192d75457f96 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 17:35:20 +0800 -Subject: [PATCH 086/140] Revert JDK-8256254: Convert vmIntrinsics::ID to enum - class - ---- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/methodHandles_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 006fe49b155..1133e80a210 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -1841,7 +1841,7 @@ void InterpreterMacroAssembler::profile_return_type(Register mdp, Register ret, - beq(t0, tmp, do_profile); - get_method(tmp); - lhu(t0, Address(tmp, Method::intrinsic_id_offset_in_bytes())); -- li(t1, static_cast(vmIntrinsics::_compiledLambdaForm)); -+ li(t1, vmIntrinsics::_compiledLambdaForm); - bne(t0, t1, profile_continue); - bind(do_profile); - } -diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -index 3bf5cfb16c3..4442b5991b1 100644 ---- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -411,7 +411,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, - } - - default: -- fatal("unexpected intrinsic %d: %s", vmIntrinsics::as_int(iid), vmIntrinsics::name_at(iid)); -+ fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); - break; - } - -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 897dafcc99c..5b934b04e8e 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1040,7 +1040,7 @@ static void gen_special_dispatch(MacroAssembler* masm, - } else if (iid == vmIntrinsics::_invokeBasic) { - has_receiver = true; - } else { -- fatal("unexpected intrinsic id %d", vmIntrinsics::as_int(iid)); -+ fatal("unexpected intrinsic id %d", iid); - } - - if (member_reg != noreg) { - -From 245d01e2cae27e41b875450f5f92751e4f36a095 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Thu, 6 Apr 2023 20:27:58 +0800 -Subject: [PATCH 087/140] Revert JDK-8216557: Aarch64: Add support for - Concurrent Class Unloading - ---- - .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 4 - - .../gc/shared/barrierSetAssembler_riscv.cpp | 71 -------- - .../gc/shared/barrierSetAssembler_riscv.hpp | 3 - - .../gc/shared/barrierSetNMethod_riscv.cpp | 171 ------------------ - .../cpu/riscv/macroAssembler_riscv.cpp | 35 +--- - .../cpu/riscv/macroAssembler_riscv.hpp | 2 - - src/hotspot/cpu/riscv/relocInfo_riscv.cpp | 1 - - src/hotspot/cpu/riscv/riscv.ad | 16 -- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 7 - - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 49 ----- - src/hotspot/cpu/riscv/stubRoutines_riscv.cpp | 1 - - src/hotspot/cpu/riscv/stubRoutines_riscv.hpp | 6 - - 12 files changed, 5 insertions(+), 361 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp - -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index 44ceccd8bd1..a6d1b1470f9 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -322,10 +322,6 @@ void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { - // Note that we do this before creating a frame. - generate_stack_overflow_check(bang_size_in_bytes); - MacroAssembler::build_frame(framesize); -- -- // Insert nmethod entry barrier into frame. -- BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -- bs->nmethod_entry_barrier(this); - } - - void C1_MacroAssembler::remove_frame(int framesize) { -diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp -index 3c115a2ea02..2b556b95d71 100644 ---- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp -@@ -27,7 +27,6 @@ - #include "classfile/classLoaderData.hpp" - #include "gc/shared/barrierSet.hpp" - #include "gc/shared/barrierSetAssembler.hpp" --#include "gc/shared/barrierSetNMethod.hpp" - #include "gc/shared/collectedHeap.hpp" - #include "interpreter/interp_masm.hpp" - #include "memory/universe.hpp" -@@ -230,73 +229,3 @@ void BarrierSetAssembler::incr_allocated_bytes(MacroAssembler* masm, - } - __ sd(tmp1, Address(xthread, in_bytes(JavaThread::allocated_bytes_offset()))); - } -- --void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { -- BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); -- -- if (bs_nm == NULL) { -- return; -- } -- -- // RISCV atomic operations require that the memory address be naturally aligned. -- __ align(4); -- -- Label skip, guard; -- Address thread_disarmed_addr(xthread, in_bytes(bs_nm->thread_disarmed_offset())); -- -- __ lwu(t0, guard); -- -- // Subsequent loads of oops must occur after load of guard value. -- // BarrierSetNMethod::disarm sets guard with release semantics. -- __ membar(MacroAssembler::LoadLoad); -- __ lwu(t1, thread_disarmed_addr); -- __ beq(t0, t1, skip); -- -- int32_t offset = 0; -- __ movptr_with_offset(t0, StubRoutines::riscv::method_entry_barrier(), offset); -- __ jalr(ra, t0, offset); -- __ j(skip); -- -- __ bind(guard); -- -- assert(__ offset() % 4 == 0, "bad alignment"); -- __ emit_int32(0); // nmethod guard value. Skipped over in common case. -- -- __ bind(skip); --} -- --void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler* masm) { -- BarrierSetNMethod* bs = BarrierSet::barrier_set()->barrier_set_nmethod(); -- if (bs == NULL) { -- return; -- } -- -- Label bad_call; -- __ beqz(xmethod, bad_call); -- -- // Pointer chase to the method holder to find out if the method is concurrently unloading. -- Label method_live; -- __ load_method_holder_cld(t0, xmethod); -- -- // Is it a strong CLD? -- __ lwu(t1, Address(t0, ClassLoaderData::keep_alive_offset())); -- __ bnez(t1, method_live); -- -- // Is it a weak but alive CLD? -- __ push_reg(RegSet::of(x28, x29), sp); -- -- __ ld(x28, Address(t0, ClassLoaderData::holder_offset())); -- -- // Uses x28 & x29, so we must pass new temporaries. -- __ resolve_weak_handle(x28, x29); -- __ mv(t0, x28); -- -- __ pop_reg(RegSet::of(x28, x29), sp); -- -- __ bnez(t0, method_live); -- -- __ bind(bad_call); -- -- __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -- __ bind(method_live); --} -diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp -index b85f7f5582b..984d94f4c3d 100644 ---- a/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.hpp -@@ -28,7 +28,6 @@ - - #include "asm/macroAssembler.hpp" - #include "gc/shared/barrierSet.hpp" --#include "gc/shared/barrierSetNMethod.hpp" - #include "memory/allocation.hpp" - #include "oops/access.hpp" - -@@ -71,8 +70,6 @@ class BarrierSetAssembler: public CHeapObj { - ); - virtual void barrier_stubs_init() {} - -- virtual void nmethod_entry_barrier(MacroAssembler* masm); -- virtual void c2i_entry_barrier(MacroAssembler* masm); - virtual ~BarrierSetAssembler() {} - }; - -diff --git a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp b/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp -deleted file mode 100644 -index ae7ee4c5a44..00000000000 ---- a/src/hotspot/cpu/riscv/gc/shared/barrierSetNMethod_riscv.cpp -+++ /dev/null -@@ -1,171 +0,0 @@ --/* -- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. 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 "code/codeCache.hpp" --#include "code/nativeInst.hpp" --#include "gc/shared/barrierSetNMethod.hpp" --#include "logging/log.hpp" --#include "memory/resourceArea.hpp" --#include "runtime/sharedRuntime.hpp" --#include "runtime/registerMap.hpp" --#include "runtime/thread.hpp" --#include "utilities/align.hpp" --#include "utilities/debug.hpp" -- --class NativeNMethodBarrier: public NativeInstruction { -- address instruction_address() const { return addr_at(0); } -- -- int *guard_addr() { -- /* auipc + lwu + fence + lwu + beq + lui + addi + slli + addi + slli + jalr + j */ -- return reinterpret_cast(instruction_address() + 12 * 4); -- } -- --public: -- int get_value() { -- return Atomic::load_acquire(guard_addr()); -- } -- -- void set_value(int value) { -- Atomic::release_store(guard_addr(), value); -- } -- -- void verify() const; --}; -- --// Store the instruction bitmask, bits and name for checking the barrier. --struct CheckInsn { -- uint32_t mask; -- uint32_t bits; -- const char *name; --}; -- --static const struct CheckInsn barrierInsn[] = { -- { 0x00000fff, 0x00000297, "auipc t0, 0 "}, -- { 0x000fffff, 0x0002e283, "lwu t0, 48(t0) "}, -- { 0xffffffff, 0x0aa0000f, "fence ir, ir "}, -- { 0x000fffff, 0x000be303, "lwu t1, 112(xthread)"}, -- { 0x01fff07f, 0x00628063, "beq t0, t1, skip "}, -- { 0x00000fff, 0x000002b7, "lui t0, imm0 "}, -- { 0x000fffff, 0x00028293, "addi t0, t0, imm1 "}, -- { 0xffffffff, 0x00b29293, "slli t0, t0, 11 "}, -- { 0x000fffff, 0x00028293, "addi t0, t0, imm2 "}, -- { 0xffffffff, 0x00529293, "slli t0, t0, 5 "}, -- { 0x000fffff, 0x000280e7, "jalr ra, imm3(t0) "}, -- { 0x00000fff, 0x0000006f, "j skip "} -- /* guard: */ -- /* 32bit nmethod guard value */ -- /* skip: */ --}; -- --// The encodings must match the instructions emitted by --// BarrierSetAssembler::nmethod_entry_barrier. The matching ignores the specific --// register numbers and immediate values in the encoding. --void NativeNMethodBarrier::verify() const { -- intptr_t addr = (intptr_t) instruction_address(); -- for(unsigned int i = 0; i < sizeof(barrierInsn)/sizeof(struct CheckInsn); i++ ) { -- uint32_t inst = *((uint32_t*) addr); -- if ((inst & barrierInsn[i].mask) != barrierInsn[i].bits) { -- tty->print_cr("Addr: " INTPTR_FORMAT " Code: 0x%x", addr, inst); -- fatal("not an %s instruction.", barrierInsn[i].name); -- } -- addr += 4; -- } --} -- -- --/* We're called from an nmethod when we need to deoptimize it. We do -- this by throwing away the nmethod's frame and jumping to the -- ic_miss stub. This looks like there has been an IC miss at the -- entry of the nmethod, so we resolve the call, which will fall back -- to the interpreter if the nmethod has been unloaded. */ --void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { -- -- typedef struct { -- intptr_t *sp; intptr_t *fp; address ra; address pc; -- } frame_pointers_t; -- -- frame_pointers_t *new_frame = (frame_pointers_t *)(return_address_ptr - 5); -- -- JavaThread *thread = JavaThread::current(); -- RegisterMap reg_map(thread, false); -- frame frame = thread->last_frame(); -- -- assert(frame.is_compiled_frame() || frame.is_native_frame(), "must be"); -- assert(frame.cb() == nm, "must be"); -- frame = frame.sender(®_map); -- -- LogTarget(Trace, nmethod, barrier) out; -- if (out.is_enabled()) { -- ResourceMark mark; -- log_trace(nmethod, barrier)("deoptimize(nmethod: %s(%p), return_addr: %p, osr: %d, thread: %p(%s), making rsp: %p) -> %p", -- nm->method()->name_and_sig_as_C_string(), -- nm, *(address *) return_address_ptr, nm->is_osr_method(), thread, -- thread->name(), frame.sp(), nm->verified_entry_point()); -- } -- -- new_frame->sp = frame.sp(); -- new_frame->fp = frame.fp(); -- new_frame->ra = frame.pc(); -- new_frame->pc = SharedRuntime::get_handle_wrong_method_stub(); --} -- --// This is the offset of the entry barrier from where the frame is completed. --// If any code changes between the end of the verified entry where the entry --// barrier resides, and the completion of the frame, then --// NativeNMethodCmpBarrier::verify() will immediately complain when it does --// not find the expected native instruction at this offset, which needs updating. --// Note that this offset is invariant of PreserveFramePointer. -- --// see BarrierSetAssembler::nmethod_entry_barrier --// auipc + lwu + fence + lwu + beq + movptr_with_offset(5 instructions) + jalr + j + int32 --static const int entry_barrier_offset = -4 * 13; -- --static NativeNMethodBarrier* native_nmethod_barrier(nmethod* nm) { -- address barrier_address = nm->code_begin() + nm->frame_complete_offset() + entry_barrier_offset; -- NativeNMethodBarrier* barrier = reinterpret_cast(barrier_address); -- debug_only(barrier->verify()); -- return barrier; --} -- --void BarrierSetNMethod::disarm(nmethod* nm) { -- if (!supports_entry_barrier(nm)) { -- return; -- } -- -- // Disarms the nmethod guard emitted by BarrierSetAssembler::nmethod_entry_barrier. -- NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); -- -- barrier->set_value(disarmed_value()); --} -- --bool BarrierSetNMethod::is_armed(nmethod* nm) { -- if (!supports_entry_barrier(nm)) { -- return false; -- } -- -- NativeNMethodBarrier* barrier = native_nmethod_barrier(nm); -- return barrier->get_value() != disarmed_value(); --} -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 41a415ef2cf..a75bd9dfa89 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1638,10 +1638,10 @@ void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp, - beq(trial_klass, tmp, L); - } - --// Move an oop into a register. immediate is true if we want --// immediate instructions and nmethod entry barriers are not enabled. --// i.e. we are not going to patch this instruction while the code is being --// executed by another thread. -+// Move an oop into a register. immediate is true if we want -+// immediate instructions, i.e. we are not going to patch this -+// instruction while the code is being executed by another thread. In -+// that case we can use move immediates rather than the constant pool. - void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) { - int oop_index; - if (obj == NULL) { -@@ -1656,11 +1656,7 @@ void MacroAssembler::movoop(Register dst, jobject obj, bool immediate) { - oop_index = oop_recorder()->find_index(obj); - } - RelocationHolder rspec = oop_Relocation::spec(oop_index); -- -- // nmethod entry barrier necessitate using the constant pool. They have to be -- // ordered with respected to oop access. -- // Using immediate literals would necessitate fence.i. -- if (BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate) { -+ if (!immediate) { - address dummy = address(uintptr_t(pc()) & -wordSize); // A nearby aligned address - ld_constant(dst, Address(dummy, rspec)); - } else -@@ -1738,22 +1734,6 @@ void MacroAssembler::resolve_oop_handle(Register result, Register tmp) { - access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, noreg); - } - --// ((WeakHandle)result).resolve() --void MacroAssembler::resolve_weak_handle(Register result, Register tmp) { -- assert_different_registers(result, tmp); -- Label resolved; -- -- // A null weak handle resolves to null. -- beqz(result, resolved); -- -- // Only 64 bit platforms support GCs that require a tmp register -- // Only IN_HEAP loads require a thread_tmp register -- // WeakHandle::resolve is an indirection like jweak. -- access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, -- result, Address(result), tmp, noreg /* tmp_thread */); -- bind(resolved); --} -- - void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, - Register dst, Address src, - Register tmp1, Register thread_tmp) { -@@ -3195,11 +3175,6 @@ void MacroAssembler::cmpptr(Register src1, Address src2, Label& equal) { - beq(src1, t0, equal); - } - --void MacroAssembler::load_method_holder_cld(Register result, Register method) { -- load_method_holder(result, method); -- ld(result, Address(result, InstanceKlass::class_loader_data_offset())); --} -- - void MacroAssembler::load_method_holder(Register holder, Register method) { - ld(holder, Address(method, Method::const_offset())); // ConstMethod* - ld(holder, Address(holder, ConstMethod::constants_offset())); // ConstantPool* -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index dd39f67d507..b16fe904888 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -207,7 +207,6 @@ class MacroAssembler: public Assembler { - virtual void check_and_handle_earlyret(Register java_thread); - virtual void check_and_handle_popframe(Register java_thread); - -- void resolve_weak_handle(Register result, Register tmp); - void resolve_oop_handle(Register result, Register tmp = x15); - void resolve_jobject(Register value, Register thread, Register tmp); - -@@ -673,7 +672,6 @@ class MacroAssembler: public Assembler { - void cmpptr(Register src1, Address src2, Label& equal); - - void clinit_barrier(Register klass, Register tmp, Label* L_fast_path = NULL, Label* L_slow_path = NULL); -- void load_method_holder_cld(Register result, Register method); - void load_method_holder(Register holder, Register method); - - void compute_index(Register str1, Register trailing_zeros, Register match_mask, -diff --git a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp -index 228a64eae2c..047ea2276ca 100644 ---- a/src/hotspot/cpu/riscv/relocInfo_riscv.cpp -+++ b/src/hotspot/cpu/riscv/relocInfo_riscv.cpp -@@ -41,7 +41,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { - switch (type()) { - case relocInfo::oop_type: { - oop_Relocation *reloc = (oop_Relocation *)this; -- // in movoop when BarrierSet::barrier_set()->barrier_set_nmethod() != NULL || !immediate - if (NativeInstruction::is_load_pc_relative_at(addr())) { - address constptr = (address)code()->oop_addr_at(reloc->oop_index()); - bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 7ec76e72ff0..0a1838695e1 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1068,17 +1068,6 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - st->print("sd ra, [sp, #%d]\n\t", - wordSize); - if (PreserveFramePointer) { st->print("sub fp, sp, #%d\n\t", 2 * wordSize); } - st->print("sub sp, sp, #%d\n\t", framesize); -- -- if (C->stub_function() == NULL && BarrierSet::barrier_set()->barrier_set_nmethod() != NULL) { -- st->print("ld t0, [guard]\n\t"); -- st->print("membar LoadLoad\n\t"); -- st->print("ld t1, [xthread, #thread_disarmed_offset]\n\t"); -- st->print("beq t0, t1, skip\n\t"); -- st->print("jalr #nmethod_entry_barrier_stub\n\t"); -- st->print("j skip\n\t"); -- st->print("guard: int\n\t"); -- st->print("skip:\n\t"); -- } - } - #endif - -@@ -1114,11 +1103,6 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - - __ build_frame(framesize); - -- if (C->stub_function() == NULL) { -- BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -- bs->nmethod_entry_barrier(&_masm); -- } -- - if (VerifyStackAtCalls) { - Unimplemented(); - } -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 5b934b04e8e..326ba62fcb0 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -642,9 +642,6 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm - c2i_no_clinit_check_entry = __ pc(); - } - -- BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -- bs->c2i_entry_barrier(masm); -- - gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); - - __ flush(); -@@ -1290,10 +1287,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - // -2 because return address is already present and so is saved fp - __ sub(sp, sp, stack_size - 2 * wordSize); - -- BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); -- assert_cond(bs != NULL); -- bs->nmethod_entry_barrier(masm); -- - // Frame is now completed as far as size and linkage. - int frame_complete = ((intptr_t)__ pc()) - start; - -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index 0c5b0e001ee..74c38c3d044 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -2352,50 +2352,6 @@ class StubGenerator: public StubCodeGenerator { - return entry; - } - -- address generate_method_entry_barrier() { -- __ align(CodeEntryAlignment); -- StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier"); -- -- Label deoptimize_label; -- -- address start = __ pc(); -- -- __ set_last_Java_frame(sp, fp, ra, t0); -- -- __ enter(); -- __ add(t1, sp, wordSize); -- -- __ sub(sp, sp, 4 * wordSize); -- -- __ push_call_clobbered_registers(); -- -- __ mv(c_rarg0, t1); -- __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier), 1); -- -- __ reset_last_Java_frame(true); -- -- __ mv(t0, x10); -- -- __ pop_call_clobbered_registers(); -- -- __ bnez(t0, deoptimize_label); -- -- __ leave(); -- __ ret(); -- -- __ BIND(deoptimize_label); -- -- __ ld(t0, Address(sp, 0)); -- __ ld(fp, Address(sp, wordSize)); -- __ ld(ra, Address(sp, wordSize * 2)); -- __ ld(t1, Address(sp, wordSize * 3)); -- -- __ mv(sp, t0); -- __ jr(t1); -- -- return start; -- } -- - // x10 = result - // x11 = str1 - // x12 = cnt1 -@@ -3703,11 +3659,6 @@ class StubGenerator: public StubCodeGenerator { - - generate_string_indexof_stubs(); - -- BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); -- if (bs_nm != NULL) { -- StubRoutines::riscv::_method_entry_barrier = generate_method_entry_barrier(); -- } -- - StubRoutines::riscv::set_completed(); - } - -diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp -index 395a2d338e4..9202d9ec4b0 100644 ---- a/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.cpp -@@ -53,6 +53,5 @@ address StubRoutines::riscv::_string_indexof_linear_ll = NULL; - address StubRoutines::riscv::_string_indexof_linear_uu = NULL; - address StubRoutines::riscv::_string_indexof_linear_ul = NULL; - address StubRoutines::riscv::_large_byte_array_inflate = NULL; --address StubRoutines::riscv::_method_entry_barrier = NULL; - - bool StubRoutines::riscv::_completed = false; -diff --git a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp -index 51f07819c33..0c9445e18a7 100644 ---- a/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp -+++ b/src/hotspot/cpu/riscv/stubRoutines_riscv.hpp -@@ -67,8 +67,6 @@ class riscv { - static address _string_indexof_linear_ul; - static address _large_byte_array_inflate; - -- static address _method_entry_barrier; -- - static bool _completed; - - public: -@@ -145,10 +143,6 @@ class riscv { - return _large_byte_array_inflate; - } - -- static address method_entry_barrier() { -- return _method_entry_barrier; -- } -- - static bool complete() { - return _completed; - } - -From aee31440dde84c54449b5c0dbdfb43b4d3826f5a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 17:59:40 +0800 -Subject: [PATCH 088/140] Revert JDK-8223173: Implement fast class - initialization checks on AARCH64 && JDK-8227260: JNI upcalls should bypass - class initialization barrier in c2i adapter - ---- - .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 12 ------- - .../cpu/riscv/c1_MacroAssembler_riscv.cpp | 12 +++---- - src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 12 ------- - src/hotspot/cpu/riscv/interp_masm_riscv.hpp | 2 -- - .../cpu/riscv/macroAssembler_riscv.cpp | 36 ------------------- - .../cpu/riscv/macroAssembler_riscv.hpp | 3 -- - src/hotspot/cpu/riscv/riscv.ad | 11 ------ - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 30 +--------------- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 17 +++------ - 9 files changed, 11 insertions(+), 124 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -index 49653d04d81..1e482d7cc2b 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -90,18 +90,6 @@ static void select_different_registers(Register preserve, - - bool LIR_Assembler::is_small_constant(LIR_Opr opr) { Unimplemented(); return false; } - --void LIR_Assembler::clinit_barrier(ciMethod* method) { -- assert(VM_Version::supports_fast_class_init_checks(), "sanity"); -- assert(!method->holder()->is_not_initialized(), "initialization should have been started"); -- -- Label L_skip_barrier; -- -- __ mov_metadata(t1, method->holder()->constant_encoding()); -- __ clinit_barrier(t1, t0, &L_skip_barrier /* L_fast_path */); -- __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -- __ bind(L_skip_barrier); --} -- - LIR_Opr LIR_Assembler::receiverOpr() { - return FrameMap::receiver_opr; - } -diff --git a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -index a6d1b1470f9..99d981f97f4 100644 ---- a/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -317,6 +317,12 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache, L - } - - void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) { -+ // If we have to make this method not-entrant we'll overwrite its -+ // first instruction with a jump. For this action to be legal we -+ // must ensure that this first instruction is a J, JAL or NOP. -+ // Make it a NOP. -+ nop(); -+ - assert(bang_size_in_bytes >= framesize, "stack bang size incorrect"); - // Make sure there is enough stack space for this method's activation. - // Note that we do this before creating a frame. -@@ -330,12 +336,6 @@ void C1_MacroAssembler::remove_frame(int framesize) { - - - void C1_MacroAssembler::verified_entry() { -- // If we have to make this method not-entrant we'll overwrite its -- // first instruction with a jump. For this action to be legal we -- // must ensure that this first instruction is a J, JAL or NOP. -- // Make it a NOP. -- -- nop(); - } - - void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) { -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -index 1133e80a210..b50be7e726c 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp -@@ -295,18 +295,6 @@ void InterpreterMacroAssembler::load_resolved_klass_at_offset( - ld(klass, Address(klass, Array::base_offset_in_bytes())); - } - --void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no, -- Register method, -- Register cache) { -- const int method_offset = in_bytes( -- ConstantPoolCache::base_offset() + -- ((byte_no == TemplateTable::f2_byte) -- ? ConstantPoolCacheEntry::f2_offset() -- : ConstantPoolCacheEntry::f1_offset())); -- -- ld(method, Address(cache, method_offset)); // get f1 Method* --} -- - // Generate a subtype check: branch to ok_is_subtype if sub_klass is a - // subtype of super_klass. - // -diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp -index 4d8cb086f82..4126e8ee70f 100644 ---- a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp -+++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp -@@ -122,8 +122,6 @@ class InterpreterMacroAssembler: public MacroAssembler { - // Load cpool->resolved_klass_at(index). - void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp); - -- void load_resolved_method_at_index(int byte_no, Register method, Register cache); -- - void pop_ptr(Register r = x10); - void pop_i(Register r = x10); - void pop_l(Register r = x10); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index a75bd9dfa89..304b6f2b06c 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -372,36 +372,6 @@ void MacroAssembler::get_vm_result_2(Register metadata_result, Register java_thr - sd(zr, Address(java_thread, JavaThread::vm_result_2_offset())); - } - --void MacroAssembler::clinit_barrier(Register klass, Register tmp, Label* L_fast_path, Label* L_slow_path) { -- assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required"); -- assert_different_registers(klass, xthread, tmp); -- -- Label L_fallthrough, L_tmp; -- if (L_fast_path == NULL) { -- L_fast_path = &L_fallthrough; -- } else if (L_slow_path == NULL) { -- L_slow_path = &L_fallthrough; -- } -- -- // Fast path check: class is fully initialized -- lbu(tmp, Address(klass, InstanceKlass::init_state_offset())); -- sub(tmp, tmp, InstanceKlass::fully_initialized); -- beqz(tmp, *L_fast_path); -- -- // Fast path check: current thread is initializer thread -- ld(tmp, Address(klass, InstanceKlass::init_thread_offset())); -- -- if (L_slow_path == &L_fallthrough) { -- beq(xthread, tmp, *L_fast_path); -- bind(*L_slow_path); -- } else if (L_fast_path == &L_fallthrough) { -- bne(xthread, tmp, *L_slow_path); -- bind(*L_fast_path); -- } else { -- Unimplemented(); -- } --} -- - void MacroAssembler::verify_oop(Register reg, const char* s) { - if (!VerifyOops) { return; } - -@@ -3175,12 +3145,6 @@ void MacroAssembler::cmpptr(Register src1, Address src2, Label& equal) { - beq(src1, t0, equal); - } - --void MacroAssembler::load_method_holder(Register holder, Register method) { -- ld(holder, Address(method, Method::const_offset())); // ConstMethod* -- ld(holder, Address(holder, ConstMethod::constants_offset())); // ConstantPool* -- ld(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass* --} -- - // string indexof - // compute index by trailing zeros - void MacroAssembler::compute_index(Register haystack, Register trailing_zeros, -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index b16fe904888..c6b71bdbc3c 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -671,9 +671,6 @@ class MacroAssembler: public Assembler { - - void cmpptr(Register src1, Address src2, Label& equal); - -- void clinit_barrier(Register klass, Register tmp, Label* L_fast_path = NULL, Label* L_slow_path = NULL); -- void load_method_holder(Register holder, Register method); -- - void compute_index(Register str1, Register trailing_zeros, Register match_mask, - Register result, Register char_tmp, Register tmp, - bool haystack_isL); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 0a1838695e1..13546ab328b 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1085,17 +1085,6 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - - assert_cond(C != NULL); - -- if (C->clinit_barrier_on_entry()) { -- assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started"); -- -- Label L_skip_barrier; -- -- __ mov_metadata(t1, C->method()->holder()->constant_encoding()); -- __ clinit_barrier(t1, t0, &L_skip_barrier); -- __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -- __ bind(L_skip_barrier); -- } -- - int bangsize = C->output()->bang_size_in_bytes(); - if (C->output()->need_stack_bang(bangsize)) { - __ generate_stack_overflow_check(bangsize); -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index 326ba62fcb0..ae414224c5b 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -623,29 +623,10 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm - - address c2i_entry = __ pc(); - -- // Class initialization barrier for static methods -- address c2i_no_clinit_check_entry = NULL; -- if (VM_Version::supports_fast_class_init_checks()) { -- Label L_skip_barrier; -- -- { // Bypass the barrier for non-static methods -- __ lwu(t0, Address(xmethod, Method::access_flags_offset())); -- __ andi(t1, t0, JVM_ACC_STATIC); -- __ beqz(t1, L_skip_barrier); // non-static -- } -- -- __ load_method_holder(t1, xmethod); -- __ clinit_barrier(t1, t0, &L_skip_barrier); -- __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -- -- __ bind(L_skip_barrier); -- c2i_no_clinit_check_entry = __ pc(); -- } -- - gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup); - - __ flush(); -- return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); -+ return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry); - } - - int SharedRuntime::c_calling_convention(const BasicType *sig_bt, -@@ -1270,15 +1251,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - // first instruction with a jump. - __ nop(); - -- if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) { -- Label L_skip_barrier; -- __ mov_metadata(t1, method->method_holder()); // InstanceKlass* -- __ clinit_barrier(t1, t0, &L_skip_barrier); -- __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); -- -- __ bind(L_skip_barrier); -- } -- - // Generate stack overflow check - __ bang_stack_with_offset(checked_cast(StackOverflow::stack_shadow_zone_size())); - -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index bb20f228447..1f4409a9c9a 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -2307,7 +2307,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no, - const Register temp = x9; - assert_different_registers(Rcache, index, temp); - -- Label resolved, clinit_barrier_slow; -+ Label resolved; - - Bytecodes::Code code = bytecode(); - switch (code) { -@@ -2321,10 +2321,6 @@ void TemplateTable::resolve_cache_and_index(int byte_no, - __ mv(t0, (int) code); - __ beq(temp, t0, resolved); - -- // resolve first time through -- // Class initialization barrier slow path lands here as well. -- __ bind(clinit_barrier_slow); -- - address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache); - __ mv(temp, (int) code); - __ call_VM(noreg, entry, temp); -@@ -2334,13 +2330,6 @@ void TemplateTable::resolve_cache_and_index(int byte_no, - // n.b. unlike x86 Rcache is now rcpool plus the indexed offset - // so all clients ofthis method must be modified accordingly - __ bind(resolved); -- -- // Class initialization barrier for static methods -- if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) { -- __ load_resolved_method_at_index(byte_no, temp, Rcache); -- __ load_method_holder(temp, temp); -- __ clinit_barrier(temp, t0, NULL, &clinit_barrier_slow); -- } - } - - // The Rcache and index registers must be set before call -@@ -3431,7 +3420,9 @@ void TemplateTable::invokeinterface(int byte_no) { - __ profile_virtual_call(x13, x30, x9); - - // Get declaring interface class from method, and itable index -- __ load_method_holder(x10, xmethod); -+ __ ld(x10, Address(xmethod, Method::const_offset())); -+ __ ld(x10, Address(x10, ConstMethod::constants_offset())); -+ __ ld(x10, Address(x10, ConstantPool::pool_holder_offset_in_bytes())); - __ lwu(xmethod, Address(xmethod, Method::itable_index_offset())); - __ subw(xmethod, xmethod, Method::itable_index_max); - __ negw(xmethod, xmethod); - -From c259a42eac0a11e080d28dabe7f745ee79a53663 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 18:36:13 +0800 -Subject: [PATCH 089/140] Revert JDK-8268119: Rename copy_os_cpu.inline.hpp - files to copy_os_cpu.hpp && JDK-8142362: Lots of code duplication in Copy - class - ---- - src/hotspot/cpu/riscv/copy_riscv.hpp | 85 +----------- - .../os_cpu/linux_riscv/copy_linux_riscv.hpp | 31 ----- - .../linux_riscv/copy_linux_riscv.inline.hpp | 124 ++++++++++++++++++ - 3 files changed, 128 insertions(+), 112 deletions(-) - delete mode 100644 src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp - create mode 100644 src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp - -diff --git a/src/hotspot/cpu/riscv/copy_riscv.hpp b/src/hotspot/cpu/riscv/copy_riscv.hpp -index bceadcc5dcc..05da242e354 100644 ---- a/src/hotspot/cpu/riscv/copy_riscv.hpp -+++ b/src/hotspot/cpu/riscv/copy_riscv.hpp -@@ -27,7 +27,10 @@ - #ifndef CPU_RISCV_COPY_RISCV_HPP - #define CPU_RISCV_COPY_RISCV_HPP - --#include OS_CPU_HEADER(copy) -+// Inline functions for memory copy and fill. -+ -+// Contains inline asm implementations -+#include OS_CPU_HEADER_INLINE(copy) - - static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { - julong* to = (julong*) tohw; -@@ -53,84 +56,4 @@ static void pd_zero_to_bytes(void* to, size_t count) { - (void)memset(to, 0, count); - } - --static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -- (void)memmove(to, from, count * HeapWordSize); --} -- --static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -- switch (count) { -- case 8: to[7] = from[7]; // fall through -- case 7: to[6] = from[6]; // fall through -- case 6: to[5] = from[5]; // fall through -- case 5: to[4] = from[4]; // fall through -- case 4: to[3] = from[3]; // fall through -- case 3: to[2] = from[2]; // fall through -- case 2: to[1] = from[1]; // fall through -- case 1: to[0] = from[0]; // fall through -- case 0: break; -- default: -- memcpy(to, from, count * HeapWordSize); -- break; -- } --} -- --static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { -- shared_disjoint_words_atomic(from, to, count); --} -- --static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -- pd_conjoint_words(from, to, count); --} -- --static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -- pd_disjoint_words(from, to, count); --} -- --static void pd_conjoint_bytes(const void* from, void* to, size_t count) { -- (void)memmove(to, from, count); --} -- --static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { -- pd_conjoint_bytes(from, to, count); --} -- --static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { -- _Copy_conjoint_jshorts_atomic(from, to, count); --} -- --static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { -- _Copy_conjoint_jints_atomic(from, to, count); --} -- --static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { -- _Copy_conjoint_jlongs_atomic(from, to, count); --} -- --static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { -- assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size."); -- _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); --} -- --static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { -- _Copy_arrayof_conjoint_bytes(from, to, count); --} -- --static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { -- _Copy_arrayof_conjoint_jshorts(from, to, count); --} -- --static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { -- _Copy_arrayof_conjoint_jints(from, to, count); --} -- --static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { -- _Copy_arrayof_conjoint_jlongs(from, to, count); --} -- --static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { -- assert(!UseCompressedOops, "foo!"); -- assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); -- _Copy_arrayof_conjoint_jlongs(from, to, count); --} -- - #endif // CPU_RISCV_COPY_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp -deleted file mode 100644 -index 147cfdf3c10..00000000000 ---- a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.hpp -+++ /dev/null -@@ -1,31 +0,0 @@ --/* -- * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP --#define OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP -- --// Empty for build system -- --#endif // OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_HPP -diff --git a/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp -new file mode 100644 -index 00000000000..bdf36d6b4c3 ---- /dev/null -+++ b/src/hotspot/os_cpu/linux_riscv/copy_linux_riscv.inline.hpp -@@ -0,0 +1,124 @@ -+/* -+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP -+#define OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP -+ -+static void pd_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ (void)memmove(to, from, count * HeapWordSize); -+} -+ -+static void pd_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ switch (count) { -+ case 8: to[7] = from[7]; // fall through -+ case 7: to[6] = from[6]; // fall through -+ case 6: to[5] = from[5]; // fall through -+ case 5: to[4] = from[4]; // fall through -+ case 4: to[3] = from[3]; // fall through -+ case 3: to[2] = from[2]; // fall through -+ case 2: to[1] = from[1]; // fall through -+ case 1: to[0] = from[0]; // fall through -+ case 0: break; -+ default: -+ memcpy(to, from, count * HeapWordSize); -+ break; -+ } -+} -+ -+static void pd_disjoint_words_atomic(const HeapWord* from, HeapWord* to, size_t count) { -+ switch (count) { -+ case 8: to[7] = from[7]; -+ case 7: to[6] = from[6]; -+ case 6: to[5] = from[5]; -+ case 5: to[4] = from[4]; -+ case 4: to[3] = from[3]; -+ case 3: to[2] = from[2]; -+ case 2: to[1] = from[1]; -+ case 1: to[0] = from[0]; -+ case 0: break; -+ default: -+ while (count-- > 0) { -+ *to++ = *from++; -+ } -+ break; -+ } -+} -+ -+static void pd_aligned_conjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ pd_conjoint_words(from, to, count); -+} -+ -+static void pd_aligned_disjoint_words(const HeapWord* from, HeapWord* to, size_t count) { -+ pd_disjoint_words(from, to, count); -+} -+ -+static void pd_conjoint_bytes(const void* from, void* to, size_t count) { -+ (void)memmove(to, from, count); -+} -+ -+static void pd_conjoint_bytes_atomic(const void* from, void* to, size_t count) { -+ pd_conjoint_bytes(from, to, count); -+} -+ -+static void pd_conjoint_jshorts_atomic(const jshort* from, jshort* to, size_t count) { -+ _Copy_conjoint_jshorts_atomic(from, to, count); -+} -+ -+static void pd_conjoint_jints_atomic(const jint* from, jint* to, size_t count) { -+ _Copy_conjoint_jints_atomic(from, to, count); -+} -+ -+static void pd_conjoint_jlongs_atomic(const jlong* from, jlong* to, size_t count) { -+ _Copy_conjoint_jlongs_atomic(from, to, count); -+} -+ -+static void pd_conjoint_oops_atomic(const oop* from, oop* to, size_t count) { -+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size."); -+ _Copy_conjoint_jlongs_atomic((const jlong*)from, (jlong*)to, count); -+} -+ -+static void pd_arrayof_conjoint_bytes(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_bytes(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jshorts(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jshorts(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jints(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jints(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_jlongs(const HeapWord* from, HeapWord* to, size_t count) { -+ _Copy_arrayof_conjoint_jlongs(from, to, count); -+} -+ -+static void pd_arrayof_conjoint_oops(const HeapWord* from, HeapWord* to, size_t count) { -+ assert(!UseCompressedOops, "foo!"); -+ assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); -+ _Copy_arrayof_conjoint_jlongs(from, to, count); -+} -+ -+#endif // OS_CPU_LINUX_RISCV_VM_COPY_LINUX_RISCV_INLINE_HPP - -From 6033e30ebd94f2315bf809a42ef00c85bdbc780e Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 29 Apr 2023 19:33:21 +0800 -Subject: [PATCH 090/140] Revert JDK-8241436: C2: Factor out C2-specific code - from MacroAssembler - ---- - .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 1321 ----------------- - .../cpu/riscv/c2_MacroAssembler_riscv.hpp | 141 -- - .../cpu/riscv/macroAssembler_riscv.cpp | 1282 ++++++++++++++++ - .../cpu/riscv/macroAssembler_riscv.hpp | 103 ++ - src/hotspot/cpu/riscv/riscv.ad | 124 +- - 5 files changed, 1447 insertions(+), 1524 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp - delete mode 100644 src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp - -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -deleted file mode 100644 -index 73f84a724ca..00000000000 ---- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp -+++ /dev/null -@@ -1,1321 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#include "precompiled.hpp" --#include "asm/assembler.hpp" --#include "asm/assembler.inline.hpp" --#include "opto/c2_MacroAssembler.hpp" --#include "opto/intrinsicnode.hpp" --#include "opto/subnode.hpp" --#include "runtime/stubRoutines.hpp" -- --#ifdef PRODUCT --#define BLOCK_COMMENT(str) /* nothing */ --#define STOP(error) stop(error) --#else --#define BLOCK_COMMENT(str) block_comment(str) --#define STOP(error) block_comment(error); stop(error) --#endif -- --#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") -- --// short string --// StringUTF16.indexOfChar --// StringLatin1.indexOfChar --void C2_MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, -- Register ch, Register result, -- bool isL) --{ -- Register ch1 = t0; -- Register index = t1; -- -- BLOCK_COMMENT("string_indexof_char_short {"); -- -- Label LOOP, LOOP1, LOOP4, LOOP8; -- Label MATCH, MATCH1, MATCH2, MATCH3, -- MATCH4, MATCH5, MATCH6, MATCH7, NOMATCH; -- -- mv(result, -1); -- mv(index, zr); -- -- bind(LOOP); -- addi(t0, index, 8); -- ble(t0, cnt1, LOOP8); -- addi(t0, index, 4); -- ble(t0, cnt1, LOOP4); -- j(LOOP1); -- -- bind(LOOP8); -- isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -- beq(ch, ch1, MATCH); -- isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -- beq(ch, ch1, MATCH1); -- isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -- beq(ch, ch1, MATCH2); -- isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -- beq(ch, ch1, MATCH3); -- isL ? lbu(ch1, Address(str1, 4)) : lhu(ch1, Address(str1, 8)); -- beq(ch, ch1, MATCH4); -- isL ? lbu(ch1, Address(str1, 5)) : lhu(ch1, Address(str1, 10)); -- beq(ch, ch1, MATCH5); -- isL ? lbu(ch1, Address(str1, 6)) : lhu(ch1, Address(str1, 12)); -- beq(ch, ch1, MATCH6); -- isL ? lbu(ch1, Address(str1, 7)) : lhu(ch1, Address(str1, 14)); -- beq(ch, ch1, MATCH7); -- addi(index, index, 8); -- addi(str1, str1, isL ? 8 : 16); -- blt(index, cnt1, LOOP); -- j(NOMATCH); -- -- bind(LOOP4); -- isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -- beq(ch, ch1, MATCH); -- isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -- beq(ch, ch1, MATCH1); -- isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -- beq(ch, ch1, MATCH2); -- isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -- beq(ch, ch1, MATCH3); -- addi(index, index, 4); -- addi(str1, str1, isL ? 4 : 8); -- bge(index, cnt1, NOMATCH); -- -- bind(LOOP1); -- isL ? lbu(ch1, Address(str1)) : lhu(ch1, Address(str1)); -- beq(ch, ch1, MATCH); -- addi(index, index, 1); -- addi(str1, str1, isL ? 1 : 2); -- blt(index, cnt1, LOOP1); -- j(NOMATCH); -- -- bind(MATCH1); -- addi(index, index, 1); -- j(MATCH); -- -- bind(MATCH2); -- addi(index, index, 2); -- j(MATCH); -- -- bind(MATCH3); -- addi(index, index, 3); -- j(MATCH); -- -- bind(MATCH4); -- addi(index, index, 4); -- j(MATCH); -- -- bind(MATCH5); -- addi(index, index, 5); -- j(MATCH); -- -- bind(MATCH6); -- addi(index, index, 6); -- j(MATCH); -- -- bind(MATCH7); -- addi(index, index, 7); -- -- bind(MATCH); -- mv(result, index); -- bind(NOMATCH); -- BLOCK_COMMENT("} string_indexof_char_short"); --} -- --// StringUTF16.indexOfChar --// StringLatin1.indexOfChar --void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, -- Register ch, Register result, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- bool isL) --{ -- Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; -- Register ch1 = t0; -- Register orig_cnt = t1; -- Register mask1 = tmp3; -- Register mask2 = tmp2; -- Register match_mask = tmp1; -- Register trailing_char = tmp4; -- Register unaligned_elems = tmp4; -- -- BLOCK_COMMENT("string_indexof_char {"); -- beqz(cnt1, NOMATCH); -- -- addi(t0, cnt1, isL ? -32 : -16); -- bgtz(t0, DO_LONG); -- string_indexof_char_short(str1, cnt1, ch, result, isL); -- j(DONE); -- -- bind(DO_LONG); -- mv(orig_cnt, cnt1); -- if (AvoidUnalignedAccesses) { -- Label ALIGNED; -- andi(unaligned_elems, str1, 0x7); -- beqz(unaligned_elems, ALIGNED); -- sub(unaligned_elems, unaligned_elems, 8); -- neg(unaligned_elems, unaligned_elems); -- if (!isL) { -- srli(unaligned_elems, unaligned_elems, 1); -- } -- // do unaligned part per element -- string_indexof_char_short(str1, unaligned_elems, ch, result, isL); -- bgez(result, DONE); -- mv(orig_cnt, cnt1); -- sub(cnt1, cnt1, unaligned_elems); -- bind(ALIGNED); -- } -- -- // duplicate ch -- if (isL) { -- slli(ch1, ch, 8); -- orr(ch, ch1, ch); -- } -- slli(ch1, ch, 16); -- orr(ch, ch1, ch); -- slli(ch1, ch, 32); -- orr(ch, ch1, ch); -- -- if (!isL) { -- slli(cnt1, cnt1, 1); -- } -- -- uint64_t mask0101 = UCONST64(0x0101010101010101); -- uint64_t mask0001 = UCONST64(0x0001000100010001); -- mv(mask1, isL ? mask0101 : mask0001); -- uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); -- uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); -- mv(mask2, isL ? mask7f7f : mask7fff); -- -- bind(CH1_LOOP); -- ld(ch1, Address(str1)); -- addi(str1, str1, 8); -- addi(cnt1, cnt1, -8); -- compute_match_mask(ch1, ch, match_mask, mask1, mask2); -- bnez(match_mask, HIT); -- bgtz(cnt1, CH1_LOOP); -- j(NOMATCH); -- -- bind(HIT); -- ctzc_bit(trailing_char, match_mask, isL, ch1, result); -- srli(trailing_char, trailing_char, 3); -- addi(cnt1, cnt1, 8); -- ble(cnt1, trailing_char, NOMATCH); -- // match case -- if (!isL) { -- srli(cnt1, cnt1, 1); -- srli(trailing_char, trailing_char, 1); -- } -- -- sub(result, orig_cnt, cnt1); -- add(result, result, trailing_char); -- j(DONE); -- -- bind(NOMATCH); -- mv(result, -1); -- -- bind(DONE); -- BLOCK_COMMENT("} string_indexof_char"); --} -- --typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); -- --// Search for needle in haystack and return index or -1 --// x10: result --// x11: haystack --// x12: haystack_len --// x13: needle --// x14: needle_len --void C2_MacroAssembler::string_indexof(Register haystack, Register needle, -- Register haystack_len, Register needle_len, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- Register tmp5, Register tmp6, -- Register result, int ae) --{ -- assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -- -- Label LINEARSEARCH, LINEARSTUB, DONE, NOMATCH; -- -- Register ch1 = t0; -- Register ch2 = t1; -- Register nlen_tmp = tmp1; // needle len tmp -- Register hlen_tmp = tmp2; // haystack len tmp -- Register result_tmp = tmp4; -- -- bool isLL = ae == StrIntrinsicNode::LL; -- -- bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -- bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -- int needle_chr_shift = needle_isL ? 0 : 1; -- int haystack_chr_shift = haystack_isL ? 0 : 1; -- int needle_chr_size = needle_isL ? 1 : 2; -- int haystack_chr_size = haystack_isL ? 1 : 2; -- load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -- (load_chr_insn)&MacroAssembler::lhu; -- load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -- (load_chr_insn)&MacroAssembler::lhu; -- -- BLOCK_COMMENT("string_indexof {"); -- -- // Note, inline_string_indexOf() generates checks: -- // if (pattern.count > src.count) return -1; -- // if (pattern.count == 0) return 0; -- -- // We have two strings, a source string in haystack, haystack_len and a pattern string -- // in needle, needle_len. Find the first occurence of pattern in source or return -1. -- -- // For larger pattern and source we use a simplified Boyer Moore algorithm. -- // With a small pattern and source we use linear scan. -- -- // needle_len >=8 && needle_len < 256 && needle_len < haystack_len/4, use bmh algorithm. -- sub(result_tmp, haystack_len, needle_len); -- // needle_len < 8, use linear scan -- sub(t0, needle_len, 8); -- bltz(t0, LINEARSEARCH); -- // needle_len >= 256, use linear scan -- sub(t0, needle_len, 256); -- bgez(t0, LINEARSTUB); -- // needle_len >= haystack_len/4, use linear scan -- srli(t0, haystack_len, 2); -- bge(needle_len, t0, LINEARSTUB); -- -- // Boyer-Moore-Horspool introduction: -- // The Boyer Moore alogorithm is based on the description here:- -- // -- // http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm -- // -- // This describes and algorithm with 2 shift rules. The 'Bad Character' rule -- // and the 'Good Suffix' rule. -- // -- // These rules are essentially heuristics for how far we can shift the -- // pattern along the search string. -- // -- // The implementation here uses the 'Bad Character' rule only because of the -- // complexity of initialisation for the 'Good Suffix' rule. -- // -- // This is also known as the Boyer-Moore-Horspool algorithm: -- // -- // http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm -- // -- // #define ASIZE 256 -- // -- // int bm(unsigned char *pattern, int m, unsigned char *src, int n) { -- // int i, j; -- // unsigned c; -- // unsigned char bc[ASIZE]; -- // -- // /* Preprocessing */ -- // for (i = 0; i < ASIZE; ++i) -- // bc[i] = m; -- // for (i = 0; i < m - 1; ) { -- // c = pattern[i]; -- // ++i; -- // // c < 256 for Latin1 string, so, no need for branch -- // #ifdef PATTERN_STRING_IS_LATIN1 -- // bc[c] = m - i; -- // #else -- // if (c < ASIZE) bc[c] = m - i; -- // #endif -- // } -- // -- // /* Searching */ -- // j = 0; -- // while (j <= n - m) { -- // c = src[i+j]; -- // if (pattern[m-1] == c) -- // int k; -- // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -- // if (k < 0) return j; -- // // c < 256 for Latin1 string, so, no need for branch -- // #ifdef SOURCE_STRING_IS_LATIN1_AND_PATTERN_STRING_IS_LATIN1 -- // // LL case: (c< 256) always true. Remove branch -- // j += bc[pattern[j+m-1]]; -- // #endif -- // #ifdef SOURCE_STRING_IS_UTF_AND_PATTERN_STRING_IS_UTF -- // // UU case: need if (c if not. -- // if (c < ASIZE) -- // j += bc[pattern[j+m-1]]; -- // else -- // j += m -- // #endif -- // } -- // return -1; -- // } -- -- // temp register:t0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, result -- Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH, -- BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP; -- -- Register haystack_end = haystack_len; -- Register skipch = tmp2; -- -- // pattern length is >=8, so, we can read at least 1 register for cases when -- // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for -- // UL case. We'll re-read last character in inner pre-loop code to have -- // single outer pre-loop load -- const int firstStep = isLL ? 7 : 3; -- -- const int ASIZE = 256; -- const int STORE_BYTES = 8; // 8 bytes stored per instruction(sd) -- -- sub(sp, sp, ASIZE); -- -- // init BC offset table with default value: needle_len -- slli(t0, needle_len, 8); -- orr(t0, t0, needle_len); // [63...16][needle_len][needle_len] -- slli(tmp1, t0, 16); -- orr(t0, tmp1, t0); // [63...32][needle_len][needle_len][needle_len][needle_len] -- slli(tmp1, t0, 32); -- orr(tmp5, tmp1, t0); // tmp5: 8 elements [needle_len] -- -- mv(ch1, sp); // ch1 is t0 -- mv(tmp6, ASIZE / STORE_BYTES); // loop iterations -- -- bind(BM_INIT_LOOP); -- // for (i = 0; i < ASIZE; ++i) -- // bc[i] = m; -- for (int i = 0; i < 4; i++) { -- sd(tmp5, Address(ch1, i * wordSize)); -- } -- add(ch1, ch1, 32); -- sub(tmp6, tmp6, 4); -- bgtz(tmp6, BM_INIT_LOOP); -- -- sub(nlen_tmp, needle_len, 1); // m - 1, index of the last element in pattern -- Register orig_haystack = tmp5; -- mv(orig_haystack, haystack); -- // result_tmp = tmp4 -- shadd(haystack_end, result_tmp, haystack, haystack_end, haystack_chr_shift); -- sub(ch2, needle_len, 1); // bc offset init value, ch2 is t1 -- mv(tmp3, needle); -- -- // for (i = 0; i < m - 1; ) { -- // c = pattern[i]; -- // ++i; -- // // c < 256 for Latin1 string, so, no need for branch -- // #ifdef PATTERN_STRING_IS_LATIN1 -- // bc[c] = m - i; -- // #else -- // if (c < ASIZE) bc[c] = m - i; -- // #endif -- // } -- bind(BCLOOP); -- (this->*needle_load_1chr)(ch1, Address(tmp3), noreg); -- add(tmp3, tmp3, needle_chr_size); -- if (!needle_isL) { -- // ae == StrIntrinsicNode::UU -- mv(tmp6, ASIZE); -- bgeu(ch1, tmp6, BCSKIP); -- } -- add(tmp4, sp, ch1); -- sb(ch2, Address(tmp4)); // store skip offset to BC offset table -- -- bind(BCSKIP); -- sub(ch2, ch2, 1); // for next pattern element, skip distance -1 -- bgtz(ch2, BCLOOP); -- -- // tmp6: pattern end, address after needle -- shadd(tmp6, needle_len, needle, tmp6, needle_chr_shift); -- if (needle_isL == haystack_isL) { -- // load last 8 bytes (8LL/4UU symbols) -- ld(tmp6, Address(tmp6, -wordSize)); -- } else { -- // UL: from UTF-16(source) search Latin1(pattern) -- lwu(tmp6, Address(tmp6, -wordSize / 2)); // load last 4 bytes(4 symbols) -- // convert Latin1 to UTF. eg: 0x0000abcd -> 0x0a0b0c0d -- // We'll have to wait until load completed, but it's still faster than per-character loads+checks -- srli(tmp3, tmp6, BitsPerByte * (wordSize / 2 - needle_chr_size)); // pattern[m-1], eg:0x0000000a -- slli(ch2, tmp6, XLEN - 24); -- srli(ch2, ch2, XLEN - 8); // pattern[m-2], 0x0000000b -- slli(ch1, tmp6, XLEN - 16); -- srli(ch1, ch1, XLEN - 8); // pattern[m-3], 0x0000000c -- andi(tmp6, tmp6, 0xff); // pattern[m-4], 0x0000000d -- slli(ch2, ch2, 16); -- orr(ch2, ch2, ch1); // 0x00000b0c -- slli(result, tmp3, 48); // use result as temp register -- orr(tmp6, tmp6, result); // 0x0a00000d -- slli(result, ch2, 16); -- orr(tmp6, tmp6, result); // UTF-16:0x0a0b0c0d -- } -- -- // i = m - 1; -- // skipch = j + i; -- // if (skipch == pattern[m - 1] -- // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -- // else -- // move j with bad char offset table -- bind(BMLOOPSTR2); -- // compare pattern to source string backward -- shadd(result, nlen_tmp, haystack, result, haystack_chr_shift); -- (this->*haystack_load_1chr)(skipch, Address(result), noreg); -- sub(nlen_tmp, nlen_tmp, firstStep); // nlen_tmp is positive here, because needle_len >= 8 -- if (needle_isL == haystack_isL) { -- // re-init tmp3. It's for free because it's executed in parallel with -- // load above. Alternative is to initialize it before loop, but it'll -- // affect performance on in-order systems with 2 or more ld/st pipelines -- srli(tmp3, tmp6, BitsPerByte * (wordSize - needle_chr_size)); // UU/LL: pattern[m-1] -- } -- if (!isLL) { // UU/UL case -- slli(ch2, nlen_tmp, 1); // offsets in bytes -- } -- bne(tmp3, skipch, BMSKIP); // if not equal, skipch is bad char -- add(result, haystack, isLL ? nlen_tmp : ch2); -- ld(ch2, Address(result)); // load 8 bytes from source string -- mv(ch1, tmp6); -- if (isLL) { -- j(BMLOOPSTR1_AFTER_LOAD); -- } else { -- sub(nlen_tmp, nlen_tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8 -- j(BMLOOPSTR1_CMP); -- } -- -- bind(BMLOOPSTR1); -- shadd(ch1, nlen_tmp, needle, ch1, needle_chr_shift); -- (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -- shadd(ch2, nlen_tmp, haystack, ch2, haystack_chr_shift); -- (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -- -- bind(BMLOOPSTR1_AFTER_LOAD); -- sub(nlen_tmp, nlen_tmp, 1); -- bltz(nlen_tmp, BMLOOPSTR1_LASTCMP); -- -- bind(BMLOOPSTR1_CMP); -- beq(ch1, ch2, BMLOOPSTR1); -- -- bind(BMSKIP); -- if (!isLL) { -- // if we've met UTF symbol while searching Latin1 pattern, then we can -- // skip needle_len symbols -- if (needle_isL != haystack_isL) { -- mv(result_tmp, needle_len); -- } else { -- mv(result_tmp, 1); -- } -- mv(t0, ASIZE); -- bgeu(skipch, t0, BMADV); -- } -- add(result_tmp, sp, skipch); -- lbu(result_tmp, Address(result_tmp)); // load skip offset -- -- bind(BMADV); -- sub(nlen_tmp, needle_len, 1); -- // move haystack after bad char skip offset -- shadd(haystack, result_tmp, haystack, result, haystack_chr_shift); -- ble(haystack, haystack_end, BMLOOPSTR2); -- add(sp, sp, ASIZE); -- j(NOMATCH); -- -- bind(BMLOOPSTR1_LASTCMP); -- bne(ch1, ch2, BMSKIP); -- -- bind(BMMATCH); -- sub(result, haystack, orig_haystack); -- if (!haystack_isL) { -- srli(result, result, 1); -- } -- add(sp, sp, ASIZE); -- j(DONE); -- -- bind(LINEARSTUB); -- sub(t0, needle_len, 16); // small patterns still should be handled by simple algorithm -- bltz(t0, LINEARSEARCH); -- mv(result, zr); -- RuntimeAddress stub = NULL; -- if (isLL) { -- stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ll()); -- assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated"); -- } else if (needle_isL) { -- stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ul()); -- assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated"); -- } else { -- stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); -- assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); -- } -- trampoline_call(stub); -- j(DONE); -- -- bind(NOMATCH); -- mv(result, -1); -- j(DONE); -- -- bind(LINEARSEARCH); -- string_indexof_linearscan(haystack, needle, haystack_len, needle_len, tmp1, tmp2, tmp3, tmp4, -1, result, ae); -- -- bind(DONE); -- BLOCK_COMMENT("} string_indexof"); --} -- --// string_indexof --// result: x10 --// src: x11 --// src_count: x12 --// pattern: x13 --// pattern_count: x14 or 1/2/3/4 --void C2_MacroAssembler::string_indexof_linearscan(Register haystack, Register needle, -- Register haystack_len, Register needle_len, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- int needle_con_cnt, Register result, int ae) --{ -- // Note: -- // needle_con_cnt > 0 means needle_len register is invalid, needle length is constant -- // for UU/LL: needle_con_cnt[1, 4], UL: needle_con_cnt = 1 -- assert(needle_con_cnt <= 4, "Invalid needle constant count"); -- assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -- -- Register ch1 = t0; -- Register ch2 = t1; -- Register hlen_neg = haystack_len, nlen_neg = needle_len; -- Register nlen_tmp = tmp1, hlen_tmp = tmp2, result_tmp = tmp4; -- -- bool isLL = ae == StrIntrinsicNode::LL; -- -- bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -- bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -- int needle_chr_shift = needle_isL ? 0 : 1; -- int haystack_chr_shift = haystack_isL ? 0 : 1; -- int needle_chr_size = needle_isL ? 1 : 2; -- int haystack_chr_size = haystack_isL ? 1 : 2; -- -- load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -- (load_chr_insn)&MacroAssembler::lhu; -- load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -- (load_chr_insn)&MacroAssembler::lhu; -- load_chr_insn load_2chr = isLL ? (load_chr_insn)&MacroAssembler::lhu : (load_chr_insn)&MacroAssembler::lwu; -- load_chr_insn load_4chr = isLL ? (load_chr_insn)&MacroAssembler::lwu : (load_chr_insn)&MacroAssembler::ld; -- -- Label DO1, DO2, DO3, MATCH, NOMATCH, DONE; -- -- Register first = tmp3; -- -- if (needle_con_cnt == -1) { -- Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT; -- -- sub(t0, needle_len, needle_isL == haystack_isL ? 4 : 2); -- bltz(t0, DOSHORT); -- -- (this->*needle_load_1chr)(first, Address(needle), noreg); -- slli(t0, needle_len, needle_chr_shift); -- add(needle, needle, t0); -- neg(nlen_neg, t0); -- slli(t0, result_tmp, haystack_chr_shift); -- add(haystack, haystack, t0); -- neg(hlen_neg, t0); -- -- bind(FIRST_LOOP); -- add(t0, haystack, hlen_neg); -- (this->*haystack_load_1chr)(ch2, Address(t0), noreg); -- beq(first, ch2, STR1_LOOP); -- -- bind(STR2_NEXT); -- add(hlen_neg, hlen_neg, haystack_chr_size); -- blez(hlen_neg, FIRST_LOOP); -- j(NOMATCH); -- -- bind(STR1_LOOP); -- add(nlen_tmp, nlen_neg, needle_chr_size); -- add(hlen_tmp, hlen_neg, haystack_chr_size); -- bgez(nlen_tmp, MATCH); -- -- bind(STR1_NEXT); -- add(ch1, needle, nlen_tmp); -- (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -- add(ch2, haystack, hlen_tmp); -- (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -- bne(ch1, ch2, STR2_NEXT); -- add(nlen_tmp, nlen_tmp, needle_chr_size); -- add(hlen_tmp, hlen_tmp, haystack_chr_size); -- bltz(nlen_tmp, STR1_NEXT); -- j(MATCH); -- -- bind(DOSHORT); -- if (needle_isL == haystack_isL) { -- sub(t0, needle_len, 2); -- bltz(t0, DO1); -- bgtz(t0, DO3); -- } -- } -- -- if (needle_con_cnt == 4) { -- Label CH1_LOOP; -- (this->*load_4chr)(ch1, Address(needle), noreg); -- sub(result_tmp, haystack_len, 4); -- slli(tmp3, result_tmp, haystack_chr_shift); // result as tmp -- add(haystack, haystack, tmp3); -- neg(hlen_neg, tmp3); -- -- bind(CH1_LOOP); -- add(ch2, haystack, hlen_neg); -- (this->*load_4chr)(ch2, Address(ch2), noreg); -- beq(ch1, ch2, MATCH); -- add(hlen_neg, hlen_neg, haystack_chr_size); -- blez(hlen_neg, CH1_LOOP); -- j(NOMATCH); -- } -- -- if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 2) { -- Label CH1_LOOP; -- BLOCK_COMMENT("string_indexof DO2 {"); -- bind(DO2); -- (this->*load_2chr)(ch1, Address(needle), noreg); -- if (needle_con_cnt == 2) { -- sub(result_tmp, haystack_len, 2); -- } -- slli(tmp3, result_tmp, haystack_chr_shift); -- add(haystack, haystack, tmp3); -- neg(hlen_neg, tmp3); -- -- bind(CH1_LOOP); -- add(tmp3, haystack, hlen_neg); -- (this->*load_2chr)(ch2, Address(tmp3), noreg); -- beq(ch1, ch2, MATCH); -- add(hlen_neg, hlen_neg, haystack_chr_size); -- blez(hlen_neg, CH1_LOOP); -- j(NOMATCH); -- BLOCK_COMMENT("} string_indexof DO2"); -- } -- -- if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 3) { -- Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; -- BLOCK_COMMENT("string_indexof DO3 {"); -- -- bind(DO3); -- (this->*load_2chr)(first, Address(needle), noreg); -- (this->*needle_load_1chr)(ch1, Address(needle, 2 * needle_chr_size), noreg); -- if (needle_con_cnt == 3) { -- sub(result_tmp, haystack_len, 3); -- } -- slli(hlen_tmp, result_tmp, haystack_chr_shift); -- add(haystack, haystack, hlen_tmp); -- neg(hlen_neg, hlen_tmp); -- -- bind(FIRST_LOOP); -- add(ch2, haystack, hlen_neg); -- (this->*load_2chr)(ch2, Address(ch2), noreg); -- beq(first, ch2, STR1_LOOP); -- -- bind(STR2_NEXT); -- add(hlen_neg, hlen_neg, haystack_chr_size); -- blez(hlen_neg, FIRST_LOOP); -- j(NOMATCH); -- -- bind(STR1_LOOP); -- add(hlen_tmp, hlen_neg, 2 * haystack_chr_size); -- add(ch2, haystack, hlen_tmp); -- (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -- bne(ch1, ch2, STR2_NEXT); -- j(MATCH); -- BLOCK_COMMENT("} string_indexof DO3"); -- } -- -- if (needle_con_cnt == -1 || needle_con_cnt == 1) { -- Label DO1_LOOP; -- -- BLOCK_COMMENT("string_indexof DO1 {"); -- bind(DO1); -- (this->*needle_load_1chr)(ch1, Address(needle), noreg); -- sub(result_tmp, haystack_len, 1); -- mv(tmp3, result_tmp); -- if (haystack_chr_shift) { -- slli(tmp3, result_tmp, haystack_chr_shift); -- } -- add(haystack, haystack, tmp3); -- neg(hlen_neg, tmp3); -- -- bind(DO1_LOOP); -- add(tmp3, haystack, hlen_neg); -- (this->*haystack_load_1chr)(ch2, Address(tmp3), noreg); -- beq(ch1, ch2, MATCH); -- add(hlen_neg, hlen_neg, haystack_chr_size); -- blez(hlen_neg, DO1_LOOP); -- BLOCK_COMMENT("} string_indexof DO1"); -- } -- -- bind(NOMATCH); -- mv(result, -1); -- j(DONE); -- -- bind(MATCH); -- srai(t0, hlen_neg, haystack_chr_shift); -- add(result, result_tmp, t0); -- -- bind(DONE); --} -- --// Compare strings. --void C2_MacroAssembler::string_compare(Register str1, Register str2, -- Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, -- Register tmp3, int ae) --{ -- Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, -- DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, -- SHORT_LOOP_START, TAIL_CHECK, L; -- -- const int STUB_THRESHOLD = 64 + 8; -- bool isLL = ae == StrIntrinsicNode::LL; -- bool isLU = ae == StrIntrinsicNode::LU; -- bool isUL = ae == StrIntrinsicNode::UL; -- -- bool str1_isL = isLL || isLU; -- bool str2_isL = isLL || isUL; -- -- // for L strings, 1 byte for 1 character -- // for U strings, 2 bytes for 1 character -- int str1_chr_size = str1_isL ? 1 : 2; -- int str2_chr_size = str2_isL ? 1 : 2; -- int minCharsInWord = isLL ? wordSize : wordSize / 2; -- -- load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -- load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -- -- BLOCK_COMMENT("string_compare {"); -- -- // Bizzarely, the counts are passed in bytes, regardless of whether they -- // are L or U strings, however the result is always in characters. -- if (!str1_isL) { -- sraiw(cnt1, cnt1, 1); -- } -- if (!str2_isL) { -- sraiw(cnt2, cnt2, 1); -- } -- -- // Compute the minimum of the string lengths and save the difference in result. -- sub(result, cnt1, cnt2); -- bgt(cnt1, cnt2, L); -- mv(cnt2, cnt1); -- bind(L); -- -- // A very short string -- li(t0, minCharsInWord); -- ble(cnt2, t0, SHORT_STRING); -- -- // Compare longwords -- // load first parts of strings and finish initialization while loading -- { -- if (str1_isL == str2_isL) { // LL or UU -- // load 8 bytes once to compare -- ld(tmp1, Address(str1)); -- beq(str1, str2, DONE); -- ld(tmp2, Address(str2)); -- li(t0, STUB_THRESHOLD); -- bge(cnt2, t0, STUB); -- sub(cnt2, cnt2, minCharsInWord); -- beqz(cnt2, TAIL_CHECK); -- // convert cnt2 from characters to bytes -- if (!str1_isL) { -- slli(cnt2, cnt2, 1); -- } -- add(str2, str2, cnt2); -- add(str1, str1, cnt2); -- sub(cnt2, zr, cnt2); -- } else if (isLU) { // LU case -- lwu(tmp1, Address(str1)); -- ld(tmp2, Address(str2)); -- li(t0, STUB_THRESHOLD); -- bge(cnt2, t0, STUB); -- addi(cnt2, cnt2, -4); -- add(str1, str1, cnt2); -- sub(cnt1, zr, cnt2); -- slli(cnt2, cnt2, 1); -- add(str2, str2, cnt2); -- inflate_lo32(tmp3, tmp1); -- mv(tmp1, tmp3); -- sub(cnt2, zr, cnt2); -- addi(cnt1, cnt1, 4); -- } else { // UL case -- ld(tmp1, Address(str1)); -- lwu(tmp2, Address(str2)); -- li(t0, STUB_THRESHOLD); -- bge(cnt2, t0, STUB); -- addi(cnt2, cnt2, -4); -- slli(t0, cnt2, 1); -- sub(cnt1, zr, t0); -- add(str1, str1, t0); -- add(str2, str2, cnt2); -- inflate_lo32(tmp3, tmp2); -- mv(tmp2, tmp3); -- sub(cnt2, zr, cnt2); -- addi(cnt1, cnt1, 8); -- } -- addi(cnt2, cnt2, isUL ? 4 : 8); -- bgez(cnt2, TAIL); -- xorr(tmp3, tmp1, tmp2); -- bnez(tmp3, DIFFERENCE); -- -- // main loop -- bind(NEXT_WORD); -- if (str1_isL == str2_isL) { // LL or UU -- add(t0, str1, cnt2); -- ld(tmp1, Address(t0)); -- add(t0, str2, cnt2); -- ld(tmp2, Address(t0)); -- addi(cnt2, cnt2, 8); -- } else if (isLU) { // LU case -- add(t0, str1, cnt1); -- lwu(tmp1, Address(t0)); -- add(t0, str2, cnt2); -- ld(tmp2, Address(t0)); -- addi(cnt1, cnt1, 4); -- inflate_lo32(tmp3, tmp1); -- mv(tmp1, tmp3); -- addi(cnt2, cnt2, 8); -- } else { // UL case -- add(t0, str2, cnt2); -- lwu(tmp2, Address(t0)); -- add(t0, str1, cnt1); -- ld(tmp1, Address(t0)); -- inflate_lo32(tmp3, tmp2); -- mv(tmp2, tmp3); -- addi(cnt1, cnt1, 8); -- addi(cnt2, cnt2, 4); -- } -- bgez(cnt2, TAIL); -- -- xorr(tmp3, tmp1, tmp2); -- beqz(tmp3, NEXT_WORD); -- j(DIFFERENCE); -- bind(TAIL); -- xorr(tmp3, tmp1, tmp2); -- bnez(tmp3, DIFFERENCE); -- // Last longword. In the case where length == 4 we compare the -- // same longword twice, but that's still faster than another -- // conditional branch. -- if (str1_isL == str2_isL) { // LL or UU -- ld(tmp1, Address(str1)); -- ld(tmp2, Address(str2)); -- } else if (isLU) { // LU case -- lwu(tmp1, Address(str1)); -- ld(tmp2, Address(str2)); -- inflate_lo32(tmp3, tmp1); -- mv(tmp1, tmp3); -- } else { // UL case -- lwu(tmp2, Address(str2)); -- ld(tmp1, Address(str1)); -- inflate_lo32(tmp3, tmp2); -- mv(tmp2, tmp3); -- } -- bind(TAIL_CHECK); -- xorr(tmp3, tmp1, tmp2); -- beqz(tmp3, DONE); -- -- // Find the first different characters in the longwords and -- // compute their difference. -- bind(DIFFERENCE); -- ctzc_bit(result, tmp3, isLL); // count zero from lsb to msb -- srl(tmp1, tmp1, result); -- srl(tmp2, tmp2, result); -- if (isLL) { -- andi(tmp1, tmp1, 0xFF); -- andi(tmp2, tmp2, 0xFF); -- } else { -- andi(tmp1, tmp1, 0xFFFF); -- andi(tmp2, tmp2, 0xFFFF); -- } -- sub(result, tmp1, tmp2); -- j(DONE); -- } -- -- bind(STUB); -- RuntimeAddress stub = NULL; -- switch (ae) { -- case StrIntrinsicNode::LL: -- stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LL()); -- break; -- case StrIntrinsicNode::UU: -- stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UU()); -- break; -- case StrIntrinsicNode::LU: -- stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LU()); -- break; -- case StrIntrinsicNode::UL: -- stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UL()); -- break; -- default: -- ShouldNotReachHere(); -- } -- assert(stub.target() != NULL, "compare_long_string stub has not been generated"); -- trampoline_call(stub); -- j(DONE); -- -- bind(SHORT_STRING); -- // Is the minimum length zero? -- beqz(cnt2, DONE); -- // arrange code to do most branches while loading and loading next characters -- // while comparing previous -- (this->*str1_load_chr)(tmp1, Address(str1), t0); -- addi(str1, str1, str1_chr_size); -- addi(cnt2, cnt2, -1); -- beqz(cnt2, SHORT_LAST_INIT); -- (this->*str2_load_chr)(cnt1, Address(str2), t0); -- addi(str2, str2, str2_chr_size); -- j(SHORT_LOOP_START); -- bind(SHORT_LOOP); -- addi(cnt2, cnt2, -1); -- beqz(cnt2, SHORT_LAST); -- bind(SHORT_LOOP_START); -- (this->*str1_load_chr)(tmp2, Address(str1), t0); -- addi(str1, str1, str1_chr_size); -- (this->*str2_load_chr)(t0, Address(str2), t0); -- addi(str2, str2, str2_chr_size); -- bne(tmp1, cnt1, SHORT_LOOP_TAIL); -- addi(cnt2, cnt2, -1); -- beqz(cnt2, SHORT_LAST2); -- (this->*str1_load_chr)(tmp1, Address(str1), t0); -- addi(str1, str1, str1_chr_size); -- (this->*str2_load_chr)(cnt1, Address(str2), t0); -- addi(str2, str2, str2_chr_size); -- beq(tmp2, t0, SHORT_LOOP); -- sub(result, tmp2, t0); -- j(DONE); -- bind(SHORT_LOOP_TAIL); -- sub(result, tmp1, cnt1); -- j(DONE); -- bind(SHORT_LAST2); -- beq(tmp2, t0, DONE); -- sub(result, tmp2, t0); -- -- j(DONE); -- bind(SHORT_LAST_INIT); -- (this->*str2_load_chr)(cnt1, Address(str2), t0); -- addi(str2, str2, str2_chr_size); -- bind(SHORT_LAST); -- beq(tmp1, cnt1, DONE); -- sub(result, tmp1, cnt1); -- -- bind(DONE); -- -- BLOCK_COMMENT("} string_compare"); --} -- --void C2_MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, -- Register tmp4, Register tmp5, Register tmp6, Register result, -- Register cnt1, int elem_size) { -- Label DONE, SAME, NEXT_DWORD, SHORT, TAIL, TAIL2, IS_TMP5_ZR; -- Register tmp1 = t0; -- Register tmp2 = t1; -- Register cnt2 = tmp2; // cnt2 only used in array length compare -- Register elem_per_word = tmp6; -- int log_elem_size = exact_log2(elem_size); -- int length_offset = arrayOopDesc::length_offset_in_bytes(); -- int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); -- -- assert(elem_size == 1 || elem_size == 2, "must be char or byte"); -- assert_different_registers(a1, a2, result, cnt1, t0, t1, tmp3, tmp4, tmp5, tmp6); -- li(elem_per_word, wordSize / elem_size); -- -- BLOCK_COMMENT("arrays_equals {"); -- -- // if (a1 == a2), return true -- beq(a1, a2, SAME); -- -- mv(result, false); -- beqz(a1, DONE); -- beqz(a2, DONE); -- lwu(cnt1, Address(a1, length_offset)); -- lwu(cnt2, Address(a2, length_offset)); -- bne(cnt2, cnt1, DONE); -- beqz(cnt1, SAME); -- -- slli(tmp5, cnt1, 3 + log_elem_size); -- sub(tmp5, zr, tmp5); -- add(a1, a1, base_offset); -- add(a2, a2, base_offset); -- ld(tmp3, Address(a1, 0)); -- ld(tmp4, Address(a2, 0)); -- ble(cnt1, elem_per_word, SHORT); // short or same -- -- // Main 16 byte comparison loop with 2 exits -- bind(NEXT_DWORD); { -- ld(tmp1, Address(a1, wordSize)); -- ld(tmp2, Address(a2, wordSize)); -- sub(cnt1, cnt1, 2 * wordSize / elem_size); -- blez(cnt1, TAIL); -- bne(tmp3, tmp4, DONE); -- ld(tmp3, Address(a1, 2 * wordSize)); -- ld(tmp4, Address(a2, 2 * wordSize)); -- add(a1, a1, 2 * wordSize); -- add(a2, a2, 2 * wordSize); -- ble(cnt1, elem_per_word, TAIL2); -- } beq(tmp1, tmp2, NEXT_DWORD); -- j(DONE); -- -- bind(TAIL); -- xorr(tmp4, tmp3, tmp4); -- xorr(tmp2, tmp1, tmp2); -- sll(tmp2, tmp2, tmp5); -- orr(tmp5, tmp4, tmp2); -- j(IS_TMP5_ZR); -- -- bind(TAIL2); -- bne(tmp1, tmp2, DONE); -- -- bind(SHORT); -- xorr(tmp4, tmp3, tmp4); -- sll(tmp5, tmp4, tmp5); -- -- bind(IS_TMP5_ZR); -- bnez(tmp5, DONE); -- -- bind(SAME); -- mv(result, true); -- // That's it. -- bind(DONE); -- -- BLOCK_COMMENT("} array_equals"); --} -- --// Compare Strings -- --// For Strings we're passed the address of the first characters in a1 --// and a2 and the length in cnt1. --// elem_size is the element size in bytes: either 1 or 2. --// There are two implementations. For arrays >= 8 bytes, all --// comparisons (including the final one, which may overlap) are --// performed 8 bytes at a time. For strings < 8 bytes, we compare a --// halfword, then a short, and then a byte. -- --void C2_MacroAssembler::string_equals(Register a1, Register a2, -- Register result, Register cnt1, int elem_size) --{ -- Label SAME, DONE, SHORT, NEXT_WORD; -- Register tmp1 = t0; -- Register tmp2 = t1; -- -- assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte"); -- assert_different_registers(a1, a2, result, cnt1, t0, t1); -- -- BLOCK_COMMENT("string_equals {"); -- -- mv(result, false); -- -- // Check for short strings, i.e. smaller than wordSize. -- sub(cnt1, cnt1, wordSize); -- bltz(cnt1, SHORT); -- -- // Main 8 byte comparison loop. -- bind(NEXT_WORD); { -- ld(tmp1, Address(a1, 0)); -- add(a1, a1, wordSize); -- ld(tmp2, Address(a2, 0)); -- add(a2, a2, wordSize); -- sub(cnt1, cnt1, wordSize); -- bne(tmp1, tmp2, DONE); -- } bgtz(cnt1, NEXT_WORD); -- -- // Last longword. In the case where length == 4 we compare the -- // same longword twice, but that's still faster than another -- // conditional branch. -- // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when -- // length == 4. -- add(tmp1, a1, cnt1); -- ld(tmp1, Address(tmp1, 0)); -- add(tmp2, a2, cnt1); -- ld(tmp2, Address(tmp2, 0)); -- bne(tmp1, tmp2, DONE); -- j(SAME); -- -- bind(SHORT); -- Label TAIL03, TAIL01; -- -- // 0-7 bytes left. -- andi(t0, cnt1, 4); -- beqz(t0, TAIL03); -- { -- lwu(tmp1, Address(a1, 0)); -- add(a1, a1, 4); -- lwu(tmp2, Address(a2, 0)); -- add(a2, a2, 4); -- bne(tmp1, tmp2, DONE); -- } -- -- bind(TAIL03); -- // 0-3 bytes left. -- andi(t0, cnt1, 2); -- beqz(t0, TAIL01); -- { -- lhu(tmp1, Address(a1, 0)); -- add(a1, a1, 2); -- lhu(tmp2, Address(a2, 0)); -- add(a2, a2, 2); -- bne(tmp1, tmp2, DONE); -- } -- -- bind(TAIL01); -- if (elem_size == 1) { // Only needed when comparing 1-byte elements -- // 0-1 bytes left. -- andi(t0, cnt1, 1); -- beqz(t0, SAME); -- { -- lbu(tmp1, a1, 0); -- lbu(tmp2, a2, 0); -- bne(tmp1, tmp2, DONE); -- } -- } -- -- // Arrays are equal. -- bind(SAME); -- mv(result, true); -- -- // That's it. -- bind(DONE); -- BLOCK_COMMENT("} string_equals"); --} -- --typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far); --typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label, -- bool is_far, bool is_unordered); -- --static conditional_branch_insn conditional_branches[] = --{ -- /* SHORT branches */ -- (conditional_branch_insn)&Assembler::beq, -- (conditional_branch_insn)&Assembler::bgt, -- NULL, // BoolTest::overflow -- (conditional_branch_insn)&Assembler::blt, -- (conditional_branch_insn)&Assembler::bne, -- (conditional_branch_insn)&Assembler::ble, -- NULL, // BoolTest::no_overflow -- (conditional_branch_insn)&Assembler::bge, -- -- /* UNSIGNED branches */ -- (conditional_branch_insn)&Assembler::beq, -- (conditional_branch_insn)&Assembler::bgtu, -- NULL, -- (conditional_branch_insn)&Assembler::bltu, -- (conditional_branch_insn)&Assembler::bne, -- (conditional_branch_insn)&Assembler::bleu, -- NULL, -- (conditional_branch_insn)&Assembler::bgeu --}; -- --static float_conditional_branch_insn float_conditional_branches[] = --{ -- /* FLOAT SHORT branches */ -- (float_conditional_branch_insn)&MacroAssembler::float_beq, -- (float_conditional_branch_insn)&MacroAssembler::float_bgt, -- NULL, // BoolTest::overflow -- (float_conditional_branch_insn)&MacroAssembler::float_blt, -- (float_conditional_branch_insn)&MacroAssembler::float_bne, -- (float_conditional_branch_insn)&MacroAssembler::float_ble, -- NULL, // BoolTest::no_overflow -- (float_conditional_branch_insn)&MacroAssembler::float_bge, -- -- /* DOUBLE SHORT branches */ -- (float_conditional_branch_insn)&MacroAssembler::double_beq, -- (float_conditional_branch_insn)&MacroAssembler::double_bgt, -- NULL, -- (float_conditional_branch_insn)&MacroAssembler::double_blt, -- (float_conditional_branch_insn)&MacroAssembler::double_bne, -- (float_conditional_branch_insn)&MacroAssembler::double_ble, -- NULL, -- (float_conditional_branch_insn)&MacroAssembler::double_bge --}; -- --void C2_MacroAssembler::cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, bool is_far) { -- assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(conditional_branches) / sizeof(conditional_branches[0])), -- "invalid conditional branch index"); -- (this->*conditional_branches[cmpFlag])(op1, op2, label, is_far); --} -- --// This is a function should only be used by C2. Flip the unordered when unordered-greater, C2 would use --// unordered-lesser instead of unordered-greater. Finally, commute the result bits at function do_one_bytecode(). --void C2_MacroAssembler::float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, bool is_far) { -- assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(float_conditional_branches) / sizeof(float_conditional_branches[0])), -- "invalid float conditional branch index"); -- int booltest_flag = cmpFlag & ~(C2_MacroAssembler::double_branch_mask); -- (this->*float_conditional_branches[cmpFlag])(op1, op2, label, is_far, -- (booltest_flag == (BoolTest::ge) || booltest_flag == (BoolTest::gt)) ? false : true); --} -- --void C2_MacroAssembler::enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -- switch (cmpFlag) { -- case BoolTest::eq: -- case BoolTest::le: -- beqz(op1, L, is_far); -- break; -- case BoolTest::ne: -- case BoolTest::gt: -- bnez(op1, L, is_far); -- break; -- default: -- ShouldNotReachHere(); -- } --} -- --void C2_MacroAssembler::enc_cmpEqNe_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -- switch (cmpFlag) { -- case BoolTest::eq: -- beqz(op1, L, is_far); -- break; -- case BoolTest::ne: -- bnez(op1, L, is_far); -- break; -- default: -- ShouldNotReachHere(); -- } --} -- --void C2_MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Register dst, Register src) { -- Label L; -- cmp_branch(cmpFlag ^ (1 << neg_cond_bits), op1, op2, L); -- mv(dst, src); -- bind(L); --} -- --// Set dst to NaN if any NaN input. --void C2_MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRegister src2, -- bool is_double, bool is_min) { -- assert_different_registers(dst, src1, src2); -- -- Label Done; -- fsflags(zr); -- if (is_double) { -- is_min ? fmin_d(dst, src1, src2) -- : fmax_d(dst, src1, src2); -- // Checking NaNs -- flt_d(zr, src1, src2); -- } else { -- is_min ? fmin_s(dst, src1, src2) -- : fmax_s(dst, src1, src2); -- // Checking NaNs -- flt_s(zr, src1, src2); -- } -- -- frflags(t0); -- beqz(t0, Done); -- -- // In case of NaNs -- is_double ? fadd_d(dst, src1, src2) -- : fadd_s(dst, src1, src2); -- -- bind(Done); --} -diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -deleted file mode 100644 -index 90b6554af02..00000000000 ---- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp -+++ /dev/null -@@ -1,141 +0,0 @@ --/* -- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP --#define CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP -- --// C2_MacroAssembler contains high-level macros for C2 -- -- public: -- -- void string_compare(Register str1, Register str2, -- Register cnt1, Register cnt2, Register result, -- Register tmp1, Register tmp2, Register tmp3, -- int ae); -- -- void string_indexof_char_short(Register str1, Register cnt1, -- Register ch, Register result, -- bool isL); -- -- void string_indexof_char(Register str1, Register cnt1, -- Register ch, Register result, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- bool isL); -- -- void string_indexof(Register str1, Register str2, -- Register cnt1, Register cnt2, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- Register tmp5, Register tmp6, -- Register result, int ae); -- -- void string_indexof_linearscan(Register haystack, Register needle, -- Register haystack_len, Register needle_len, -- Register tmp1, Register tmp2, -- Register tmp3, Register tmp4, -- int needle_con_cnt, Register result, int ae); -- -- void arrays_equals(Register r1, Register r2, -- Register tmp3, Register tmp4, -- Register tmp5, Register tmp6, -- Register result, Register cnt1, -- int elem_size); -- -- void string_equals(Register r1, Register r2, -- Register result, Register cnt1, -- int elem_size); -- -- // refer to conditional_branches and float_conditional_branches -- static const int bool_test_bits = 3; -- static const int neg_cond_bits = 2; -- static const int unsigned_branch_mask = 1 << bool_test_bits; -- static const int double_branch_mask = 1 << bool_test_bits; -- -- // cmp -- void cmp_branch(int cmpFlag, -- Register op1, Register op2, -- Label& label, bool is_far = false); -- -- void float_cmp_branch(int cmpFlag, -- FloatRegister op1, FloatRegister op2, -- Label& label, bool is_far = false); -- -- void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, -- Label& L, bool is_far = false); -- -- void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, -- Label& L, bool is_far = false); -- -- void enc_cmove(int cmpFlag, -- Register op1, Register op2, -- Register dst, Register src); -- -- void spill(Register r, bool is64, int offset) { -- is64 ? sd(r, Address(sp, offset)) -- : sw(r, Address(sp, offset)); -- } -- -- void spill(FloatRegister f, bool is64, int offset) { -- is64 ? fsd(f, Address(sp, offset)) -- : fsw(f, Address(sp, offset)); -- } -- -- void spill(VectorRegister v, int offset) { -- add(t0, sp, offset); -- vs1r_v(v, t0); -- } -- -- void unspill(Register r, bool is64, int offset) { -- is64 ? ld(r, Address(sp, offset)) -- : lw(r, Address(sp, offset)); -- } -- -- void unspillu(Register r, bool is64, int offset) { -- is64 ? ld(r, Address(sp, offset)) -- : lwu(r, Address(sp, offset)); -- } -- -- void unspill(FloatRegister f, bool is64, int offset) { -- is64 ? fld(f, Address(sp, offset)) -- : flw(f, Address(sp, offset)); -- } -- -- void unspill(VectorRegister v, int offset) { -- add(t0, sp, offset); -- vl1r_v(v, t0); -- } -- -- void spill_copy_vector_stack_to_stack(int src_offset, int dst_offset, int vec_reg_size_in_bytes) { -- assert(vec_reg_size_in_bytes % 16 == 0, "unexpected vector reg size"); -- unspill(v0, src_offset); -- spill(v0, dst_offset); -- } -- -- void minmax_FD(FloatRegister dst, -- FloatRegister src1, FloatRegister src2, -- bool is_double, bool is_min); -- --#endif // CPU_RISCV_C2_MACROASSEMBLER_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 304b6f2b06c..d175a62aeeb 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -4125,3 +4125,1285 @@ void MacroAssembler::safepoint_ifence() { - ifence(); - } - -+#ifdef COMPILER2 -+// short string -+// StringUTF16.indexOfChar -+// StringLatin1.indexOfChar -+void MacroAssembler::string_indexof_char_short(Register str1, Register cnt1, -+ Register ch, Register result, -+ bool isL) -+{ -+ Register ch1 = t0; -+ Register index = t1; -+ -+ BLOCK_COMMENT("string_indexof_char_short {"); -+ -+ Label LOOP, LOOP1, LOOP4, LOOP8; -+ Label MATCH, MATCH1, MATCH2, MATCH3, -+ MATCH4, MATCH5, MATCH6, MATCH7, NOMATCH; -+ -+ mv(result, -1); -+ mv(index, zr); -+ -+ bind(LOOP); -+ addi(t0, index, 8); -+ ble(t0, cnt1, LOOP8); -+ addi(t0, index, 4); -+ ble(t0, cnt1, LOOP4); -+ j(LOOP1); -+ -+ bind(LOOP8); -+ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -+ beq(ch, ch1, MATCH); -+ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -+ beq(ch, ch1, MATCH1); -+ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -+ beq(ch, ch1, MATCH2); -+ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -+ beq(ch, ch1, MATCH3); -+ isL ? lbu(ch1, Address(str1, 4)) : lhu(ch1, Address(str1, 8)); -+ beq(ch, ch1, MATCH4); -+ isL ? lbu(ch1, Address(str1, 5)) : lhu(ch1, Address(str1, 10)); -+ beq(ch, ch1, MATCH5); -+ isL ? lbu(ch1, Address(str1, 6)) : lhu(ch1, Address(str1, 12)); -+ beq(ch, ch1, MATCH6); -+ isL ? lbu(ch1, Address(str1, 7)) : lhu(ch1, Address(str1, 14)); -+ beq(ch, ch1, MATCH7); -+ addi(index, index, 8); -+ addi(str1, str1, isL ? 8 : 16); -+ blt(index, cnt1, LOOP); -+ j(NOMATCH); -+ -+ bind(LOOP4); -+ isL ? lbu(ch1, Address(str1, 0)) : lhu(ch1, Address(str1, 0)); -+ beq(ch, ch1, MATCH); -+ isL ? lbu(ch1, Address(str1, 1)) : lhu(ch1, Address(str1, 2)); -+ beq(ch, ch1, MATCH1); -+ isL ? lbu(ch1, Address(str1, 2)) : lhu(ch1, Address(str1, 4)); -+ beq(ch, ch1, MATCH2); -+ isL ? lbu(ch1, Address(str1, 3)) : lhu(ch1, Address(str1, 6)); -+ beq(ch, ch1, MATCH3); -+ addi(index, index, 4); -+ addi(str1, str1, isL ? 4 : 8); -+ bge(index, cnt1, NOMATCH); -+ -+ bind(LOOP1); -+ isL ? lbu(ch1, Address(str1)) : lhu(ch1, Address(str1)); -+ beq(ch, ch1, MATCH); -+ addi(index, index, 1); -+ addi(str1, str1, isL ? 1 : 2); -+ blt(index, cnt1, LOOP1); -+ j(NOMATCH); -+ -+ bind(MATCH1); -+ addi(index, index, 1); -+ j(MATCH); -+ -+ bind(MATCH2); -+ addi(index, index, 2); -+ j(MATCH); -+ -+ bind(MATCH3); -+ addi(index, index, 3); -+ j(MATCH); -+ -+ bind(MATCH4); -+ addi(index, index, 4); -+ j(MATCH); -+ -+ bind(MATCH5); -+ addi(index, index, 5); -+ j(MATCH); -+ -+ bind(MATCH6); -+ addi(index, index, 6); -+ j(MATCH); -+ -+ bind(MATCH7); -+ addi(index, index, 7); -+ -+ bind(MATCH); -+ mv(result, index); -+ bind(NOMATCH); -+ BLOCK_COMMENT("} string_indexof_char_short"); -+} -+ -+// StringUTF16.indexOfChar -+// StringLatin1.indexOfChar -+void MacroAssembler::string_indexof_char(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ bool isL) -+{ -+ Label CH1_LOOP, HIT, NOMATCH, DONE, DO_LONG; -+ Register ch1 = t0; -+ Register orig_cnt = t1; -+ Register mask1 = tmp3; -+ Register mask2 = tmp2; -+ Register match_mask = tmp1; -+ Register trailing_char = tmp4; -+ Register unaligned_elems = tmp4; -+ -+ BLOCK_COMMENT("string_indexof_char {"); -+ beqz(cnt1, NOMATCH); -+ -+ addi(t0, cnt1, isL ? -32 : -16); -+ bgtz(t0, DO_LONG); -+ string_indexof_char_short(str1, cnt1, ch, result, isL); -+ j(DONE); -+ -+ bind(DO_LONG); -+ mv(orig_cnt, cnt1); -+ if (AvoidUnalignedAccesses) { -+ Label ALIGNED; -+ andi(unaligned_elems, str1, 0x7); -+ beqz(unaligned_elems, ALIGNED); -+ sub(unaligned_elems, unaligned_elems, 8); -+ neg(unaligned_elems, unaligned_elems); -+ if (!isL) { -+ srli(unaligned_elems, unaligned_elems, 1); -+ } -+ // do unaligned part per element -+ string_indexof_char_short(str1, unaligned_elems, ch, result, isL); -+ bgez(result, DONE); -+ mv(orig_cnt, cnt1); -+ sub(cnt1, cnt1, unaligned_elems); -+ bind(ALIGNED); -+ } -+ -+ // duplicate ch -+ if (isL) { -+ slli(ch1, ch, 8); -+ orr(ch, ch1, ch); -+ } -+ slli(ch1, ch, 16); -+ orr(ch, ch1, ch); -+ slli(ch1, ch, 32); -+ orr(ch, ch1, ch); -+ -+ if (!isL) { -+ slli(cnt1, cnt1, 1); -+ } -+ -+ uint64_t mask0101 = UCONST64(0x0101010101010101); -+ uint64_t mask0001 = UCONST64(0x0001000100010001); -+ mv(mask1, isL ? mask0101 : mask0001); -+ uint64_t mask7f7f = UCONST64(0x7f7f7f7f7f7f7f7f); -+ uint64_t mask7fff = UCONST64(0x7fff7fff7fff7fff); -+ mv(mask2, isL ? mask7f7f : mask7fff); -+ -+ bind(CH1_LOOP); -+ ld(ch1, Address(str1)); -+ addi(str1, str1, 8); -+ addi(cnt1, cnt1, -8); -+ compute_match_mask(ch1, ch, match_mask, mask1, mask2); -+ bnez(match_mask, HIT); -+ bgtz(cnt1, CH1_LOOP); -+ j(NOMATCH); -+ -+ bind(HIT); -+ ctzc_bit(trailing_char, match_mask, isL, ch1, result); -+ srli(trailing_char, trailing_char, 3); -+ addi(cnt1, cnt1, 8); -+ ble(cnt1, trailing_char, NOMATCH); -+ // match case -+ if (!isL) { -+ srli(cnt1, cnt1, 1); -+ srli(trailing_char, trailing_char, 1); -+ } -+ -+ sub(result, orig_cnt, cnt1); -+ add(result, result, trailing_char); -+ j(DONE); -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} string_indexof_char"); -+} -+ -+typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); -+ -+// Search for needle in haystack and return index or -1 -+// x10: result -+// x11: haystack -+// x12: haystack_len -+// x13: needle -+// x14: needle_len -+void MacroAssembler::string_indexof(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, int ae) -+{ -+ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -+ -+ Label LINEARSEARCH, LINEARSTUB, DONE, NOMATCH; -+ -+ Register ch1 = t0; -+ Register ch2 = t1; -+ Register nlen_tmp = tmp1; // needle len tmp -+ Register hlen_tmp = tmp2; // haystack len tmp -+ Register result_tmp = tmp4; -+ -+ bool isLL = ae == StrIntrinsicNode::LL; -+ -+ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -+ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -+ int needle_chr_shift = needle_isL ? 0 : 1; -+ int haystack_chr_shift = haystack_isL ? 0 : 1; -+ int needle_chr_size = needle_isL ? 1 : 2; -+ int haystack_chr_size = haystack_isL ? 1 : 2; -+ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ -+ BLOCK_COMMENT("string_indexof {"); -+ -+ // Note, inline_string_indexOf() generates checks: -+ // if (pattern.count > src.count) return -1; -+ // if (pattern.count == 0) return 0; -+ -+ // We have two strings, a source string in haystack, haystack_len and a pattern string -+ // in needle, needle_len. Find the first occurence of pattern in source or return -1. -+ -+ // For larger pattern and source we use a simplified Boyer Moore algorithm. -+ // With a small pattern and source we use linear scan. -+ -+ // needle_len >=8 && needle_len < 256 && needle_len < haystack_len/4, use bmh algorithm. -+ sub(result_tmp, haystack_len, needle_len); -+ // needle_len < 8, use linear scan -+ sub(t0, needle_len, 8); -+ bltz(t0, LINEARSEARCH); -+ // needle_len >= 256, use linear scan -+ sub(t0, needle_len, 256); -+ bgez(t0, LINEARSTUB); -+ // needle_len >= haystack_len/4, use linear scan -+ srli(t0, haystack_len, 2); -+ bge(needle_len, t0, LINEARSTUB); -+ -+ // Boyer-Moore-Horspool introduction: -+ // The Boyer Moore alogorithm is based on the description here:- -+ // -+ // http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm -+ // -+ // This describes and algorithm with 2 shift rules. The 'Bad Character' rule -+ // and the 'Good Suffix' rule. -+ // -+ // These rules are essentially heuristics for how far we can shift the -+ // pattern along the search string. -+ // -+ // The implementation here uses the 'Bad Character' rule only because of the -+ // complexity of initialisation for the 'Good Suffix' rule. -+ // -+ // This is also known as the Boyer-Moore-Horspool algorithm: -+ // -+ // http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm -+ // -+ // #define ASIZE 256 -+ // -+ // int bm(unsigned char *pattern, int m, unsigned char *src, int n) { -+ // int i, j; -+ // unsigned c; -+ // unsigned char bc[ASIZE]; -+ // -+ // /* Preprocessing */ -+ // for (i = 0; i < ASIZE; ++i) -+ // bc[i] = m; -+ // for (i = 0; i < m - 1; ) { -+ // c = pattern[i]; -+ // ++i; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef PATTERN_STRING_IS_LATIN1 -+ // bc[c] = m - i; -+ // #else -+ // if (c < ASIZE) bc[c] = m - i; -+ // #endif -+ // } -+ // -+ // /* Searching */ -+ // j = 0; -+ // while (j <= n - m) { -+ // c = src[i+j]; -+ // if (pattern[m-1] == c) -+ // int k; -+ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -+ // if (k < 0) return j; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef SOURCE_STRING_IS_LATIN1_AND_PATTERN_STRING_IS_LATIN1 -+ // // LL case: (c< 256) always true. Remove branch -+ // j += bc[pattern[j+m-1]]; -+ // #endif -+ // #ifdef SOURCE_STRING_IS_UTF_AND_PATTERN_STRING_IS_UTF -+ // // UU case: need if (c if not. -+ // if (c < ASIZE) -+ // j += bc[pattern[j+m-1]]; -+ // else -+ // j += m -+ // #endif -+ // } -+ // return -1; -+ // } -+ -+ // temp register:t0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, result -+ Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH, -+ BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP; -+ -+ Register haystack_end = haystack_len; -+ Register skipch = tmp2; -+ -+ // pattern length is >=8, so, we can read at least 1 register for cases when -+ // UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for -+ // UL case. We'll re-read last character in inner pre-loop code to have -+ // single outer pre-loop load -+ const int firstStep = isLL ? 7 : 3; -+ -+ const int ASIZE = 256; -+ const int STORE_BYTES = 8; // 8 bytes stored per instruction(sd) -+ -+ sub(sp, sp, ASIZE); -+ -+ // init BC offset table with default value: needle_len -+ slli(t0, needle_len, 8); -+ orr(t0, t0, needle_len); // [63...16][needle_len][needle_len] -+ slli(tmp1, t0, 16); -+ orr(t0, tmp1, t0); // [63...32][needle_len][needle_len][needle_len][needle_len] -+ slli(tmp1, t0, 32); -+ orr(tmp5, tmp1, t0); // tmp5: 8 elements [needle_len] -+ -+ mv(ch1, sp); // ch1 is t0 -+ mv(tmp6, ASIZE / STORE_BYTES); // loop iterations -+ -+ bind(BM_INIT_LOOP); -+ // for (i = 0; i < ASIZE; ++i) -+ // bc[i] = m; -+ for (int i = 0; i < 4; i++) { -+ sd(tmp5, Address(ch1, i * wordSize)); -+ } -+ add(ch1, ch1, 32); -+ sub(tmp6, tmp6, 4); -+ bgtz(tmp6, BM_INIT_LOOP); -+ -+ sub(nlen_tmp, needle_len, 1); // m - 1, index of the last element in pattern -+ Register orig_haystack = tmp5; -+ mv(orig_haystack, haystack); -+ // result_tmp = tmp4 -+ shadd(haystack_end, result_tmp, haystack, haystack_end, haystack_chr_shift); -+ sub(ch2, needle_len, 1); // bc offset init value, ch2 is t1 -+ mv(tmp3, needle); -+ -+ // for (i = 0; i < m - 1; ) { -+ // c = pattern[i]; -+ // ++i; -+ // // c < 256 for Latin1 string, so, no need for branch -+ // #ifdef PATTERN_STRING_IS_LATIN1 -+ // bc[c] = m - i; -+ // #else -+ // if (c < ASIZE) bc[c] = m - i; -+ // #endif -+ // } -+ bind(BCLOOP); -+ (this->*needle_load_1chr)(ch1, Address(tmp3), noreg); -+ add(tmp3, tmp3, needle_chr_size); -+ if (!needle_isL) { -+ // ae == StrIntrinsicNode::UU -+ mv(tmp6, ASIZE); -+ bgeu(ch1, tmp6, BCSKIP); -+ } -+ add(tmp4, sp, ch1); -+ sb(ch2, Address(tmp4)); // store skip offset to BC offset table -+ -+ bind(BCSKIP); -+ sub(ch2, ch2, 1); // for next pattern element, skip distance -1 -+ bgtz(ch2, BCLOOP); -+ -+ // tmp6: pattern end, address after needle -+ shadd(tmp6, needle_len, needle, tmp6, needle_chr_shift); -+ if (needle_isL == haystack_isL) { -+ // load last 8 bytes (8LL/4UU symbols) -+ ld(tmp6, Address(tmp6, -wordSize)); -+ } else { -+ // UL: from UTF-16(source) search Latin1(pattern) -+ lwu(tmp6, Address(tmp6, -wordSize / 2)); // load last 4 bytes(4 symbols) -+ // convert Latin1 to UTF. eg: 0x0000abcd -> 0x0a0b0c0d -+ // We'll have to wait until load completed, but it's still faster than per-character loads+checks -+ srli(tmp3, tmp6, BitsPerByte * (wordSize / 2 - needle_chr_size)); // pattern[m-1], eg:0x0000000a -+ slli(ch2, tmp6, XLEN - 24); -+ srli(ch2, ch2, XLEN - 8); // pattern[m-2], 0x0000000b -+ slli(ch1, tmp6, XLEN - 16); -+ srli(ch1, ch1, XLEN - 8); // pattern[m-3], 0x0000000c -+ andi(tmp6, tmp6, 0xff); // pattern[m-4], 0x0000000d -+ slli(ch2, ch2, 16); -+ orr(ch2, ch2, ch1); // 0x00000b0c -+ slli(result, tmp3, 48); // use result as temp register -+ orr(tmp6, tmp6, result); // 0x0a00000d -+ slli(result, ch2, 16); -+ orr(tmp6, tmp6, result); // UTF-16:0x0a0b0c0d -+ } -+ -+ // i = m - 1; -+ // skipch = j + i; -+ // if (skipch == pattern[m - 1] -+ // for (k = m - 2; k >= 0 && pattern[k] == src[k + j]; --k); -+ // else -+ // move j with bad char offset table -+ bind(BMLOOPSTR2); -+ // compare pattern to source string backward -+ shadd(result, nlen_tmp, haystack, result, haystack_chr_shift); -+ (this->*haystack_load_1chr)(skipch, Address(result), noreg); -+ sub(nlen_tmp, nlen_tmp, firstStep); // nlen_tmp is positive here, because needle_len >= 8 -+ if (needle_isL == haystack_isL) { -+ // re-init tmp3. It's for free because it's executed in parallel with -+ // load above. Alternative is to initialize it before loop, but it'll -+ // affect performance on in-order systems with 2 or more ld/st pipelines -+ srli(tmp3, tmp6, BitsPerByte * (wordSize - needle_chr_size)); // UU/LL: pattern[m-1] -+ } -+ if (!isLL) { // UU/UL case -+ slli(ch2, nlen_tmp, 1); // offsets in bytes -+ } -+ bne(tmp3, skipch, BMSKIP); // if not equal, skipch is bad char -+ add(result, haystack, isLL ? nlen_tmp : ch2); -+ ld(ch2, Address(result)); // load 8 bytes from source string -+ mv(ch1, tmp6); -+ if (isLL) { -+ j(BMLOOPSTR1_AFTER_LOAD); -+ } else { -+ sub(nlen_tmp, nlen_tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8 -+ j(BMLOOPSTR1_CMP); -+ } -+ -+ bind(BMLOOPSTR1); -+ shadd(ch1, nlen_tmp, needle, ch1, needle_chr_shift); -+ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -+ shadd(ch2, nlen_tmp, haystack, ch2, haystack_chr_shift); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ -+ bind(BMLOOPSTR1_AFTER_LOAD); -+ sub(nlen_tmp, nlen_tmp, 1); -+ bltz(nlen_tmp, BMLOOPSTR1_LASTCMP); -+ -+ bind(BMLOOPSTR1_CMP); -+ beq(ch1, ch2, BMLOOPSTR1); -+ -+ bind(BMSKIP); -+ if (!isLL) { -+ // if we've met UTF symbol while searching Latin1 pattern, then we can -+ // skip needle_len symbols -+ if (needle_isL != haystack_isL) { -+ mv(result_tmp, needle_len); -+ } else { -+ mv(result_tmp, 1); -+ } -+ mv(t0, ASIZE); -+ bgeu(skipch, t0, BMADV); -+ } -+ add(result_tmp, sp, skipch); -+ lbu(result_tmp, Address(result_tmp)); // load skip offset -+ -+ bind(BMADV); -+ sub(nlen_tmp, needle_len, 1); -+ // move haystack after bad char skip offset -+ shadd(haystack, result_tmp, haystack, result, haystack_chr_shift); -+ ble(haystack, haystack_end, BMLOOPSTR2); -+ add(sp, sp, ASIZE); -+ j(NOMATCH); -+ -+ bind(BMLOOPSTR1_LASTCMP); -+ bne(ch1, ch2, BMSKIP); -+ -+ bind(BMMATCH); -+ sub(result, haystack, orig_haystack); -+ if (!haystack_isL) { -+ srli(result, result, 1); -+ } -+ add(sp, sp, ASIZE); -+ j(DONE); -+ -+ bind(LINEARSTUB); -+ sub(t0, needle_len, 16); // small patterns still should be handled by simple algorithm -+ bltz(t0, LINEARSEARCH); -+ mv(result, zr); -+ RuntimeAddress stub = NULL; -+ if (isLL) { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ll()); -+ assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated"); -+ } else if (needle_isL) { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_ul()); -+ assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated"); -+ } else { -+ stub = RuntimeAddress(StubRoutines::riscv::string_indexof_linear_uu()); -+ assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated"); -+ } -+ trampoline_call(stub); -+ j(DONE); -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ j(DONE); -+ -+ bind(LINEARSEARCH); -+ string_indexof_linearscan(haystack, needle, haystack_len, needle_len, tmp1, tmp2, tmp3, tmp4, -1, result, ae); -+ -+ bind(DONE); -+ BLOCK_COMMENT("} string_indexof"); -+} -+ -+// string_indexof -+// result: x10 -+// src: x11 -+// src_count: x12 -+// pattern: x13 -+// pattern_count: x14 or 1/2/3/4 -+void MacroAssembler::string_indexof_linearscan(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ int needle_con_cnt, Register result, int ae) -+{ -+ // Note: -+ // needle_con_cnt > 0 means needle_len register is invalid, needle length is constant -+ // for UU/LL: needle_con_cnt[1, 4], UL: needle_con_cnt = 1 -+ assert(needle_con_cnt <= 4, "Invalid needle constant count"); -+ assert(ae != StrIntrinsicNode::LU, "Invalid encoding"); -+ -+ Register ch1 = t0; -+ Register ch2 = t1; -+ Register hlen_neg = haystack_len, nlen_neg = needle_len; -+ Register nlen_tmp = tmp1, hlen_tmp = tmp2, result_tmp = tmp4; -+ -+ bool isLL = ae == StrIntrinsicNode::LL; -+ -+ bool needle_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL; -+ bool haystack_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU; -+ int needle_chr_shift = needle_isL ? 0 : 1; -+ int haystack_chr_shift = haystack_isL ? 0 : 1; -+ int needle_chr_size = needle_isL ? 1 : 2; -+ int haystack_chr_size = haystack_isL ? 1 : 2; -+ -+ load_chr_insn needle_load_1chr = needle_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn haystack_load_1chr = haystack_isL ? (load_chr_insn)&MacroAssembler::lbu : -+ (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn load_2chr = isLL ? (load_chr_insn)&MacroAssembler::lhu : (load_chr_insn)&MacroAssembler::lwu; -+ load_chr_insn load_4chr = isLL ? (load_chr_insn)&MacroAssembler::lwu : (load_chr_insn)&MacroAssembler::ld; -+ -+ Label DO1, DO2, DO3, MATCH, NOMATCH, DONE; -+ -+ Register first = tmp3; -+ -+ if (needle_con_cnt == -1) { -+ Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT; -+ -+ sub(t0, needle_len, needle_isL == haystack_isL ? 4 : 2); -+ bltz(t0, DOSHORT); -+ -+ (this->*needle_load_1chr)(first, Address(needle), noreg); -+ slli(t0, needle_len, needle_chr_shift); -+ add(needle, needle, t0); -+ neg(nlen_neg, t0); -+ slli(t0, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, t0); -+ neg(hlen_neg, t0); -+ -+ bind(FIRST_LOOP); -+ add(t0, haystack, hlen_neg); -+ (this->*haystack_load_1chr)(ch2, Address(t0), noreg); -+ beq(first, ch2, STR1_LOOP); -+ -+ bind(STR2_NEXT); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, FIRST_LOOP); -+ j(NOMATCH); -+ -+ bind(STR1_LOOP); -+ add(nlen_tmp, nlen_neg, needle_chr_size); -+ add(hlen_tmp, hlen_neg, haystack_chr_size); -+ bgez(nlen_tmp, MATCH); -+ -+ bind(STR1_NEXT); -+ add(ch1, needle, nlen_tmp); -+ (this->*needle_load_1chr)(ch1, Address(ch1), noreg); -+ add(ch2, haystack, hlen_tmp); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ bne(ch1, ch2, STR2_NEXT); -+ add(nlen_tmp, nlen_tmp, needle_chr_size); -+ add(hlen_tmp, hlen_tmp, haystack_chr_size); -+ bltz(nlen_tmp, STR1_NEXT); -+ j(MATCH); -+ -+ bind(DOSHORT); -+ if (needle_isL == haystack_isL) { -+ sub(t0, needle_len, 2); -+ bltz(t0, DO1); -+ bgtz(t0, DO3); -+ } -+ } -+ -+ if (needle_con_cnt == 4) { -+ Label CH1_LOOP; -+ (this->*load_4chr)(ch1, Address(needle), noreg); -+ sub(result_tmp, haystack_len, 4); -+ slli(tmp3, result_tmp, haystack_chr_shift); // result as tmp -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(CH1_LOOP); -+ add(ch2, haystack, hlen_neg); -+ (this->*load_4chr)(ch2, Address(ch2), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, CH1_LOOP); -+ j(NOMATCH); -+ } -+ -+ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 2) { -+ Label CH1_LOOP; -+ BLOCK_COMMENT("string_indexof DO2 {"); -+ bind(DO2); -+ (this->*load_2chr)(ch1, Address(needle), noreg); -+ if (needle_con_cnt == 2) { -+ sub(result_tmp, haystack_len, 2); -+ } -+ slli(tmp3, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(CH1_LOOP); -+ add(tmp3, haystack, hlen_neg); -+ (this->*load_2chr)(ch2, Address(tmp3), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, CH1_LOOP); -+ j(NOMATCH); -+ BLOCK_COMMENT("} string_indexof DO2"); -+ } -+ -+ if ((needle_con_cnt == -1 && needle_isL == haystack_isL) || needle_con_cnt == 3) { -+ Label FIRST_LOOP, STR2_NEXT, STR1_LOOP; -+ BLOCK_COMMENT("string_indexof DO3 {"); -+ -+ bind(DO3); -+ (this->*load_2chr)(first, Address(needle), noreg); -+ (this->*needle_load_1chr)(ch1, Address(needle, 2 * needle_chr_size), noreg); -+ if (needle_con_cnt == 3) { -+ sub(result_tmp, haystack_len, 3); -+ } -+ slli(hlen_tmp, result_tmp, haystack_chr_shift); -+ add(haystack, haystack, hlen_tmp); -+ neg(hlen_neg, hlen_tmp); -+ -+ bind(FIRST_LOOP); -+ add(ch2, haystack, hlen_neg); -+ (this->*load_2chr)(ch2, Address(ch2), noreg); -+ beq(first, ch2, STR1_LOOP); -+ -+ bind(STR2_NEXT); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, FIRST_LOOP); -+ j(NOMATCH); -+ -+ bind(STR1_LOOP); -+ add(hlen_tmp, hlen_neg, 2 * haystack_chr_size); -+ add(ch2, haystack, hlen_tmp); -+ (this->*haystack_load_1chr)(ch2, Address(ch2), noreg); -+ bne(ch1, ch2, STR2_NEXT); -+ j(MATCH); -+ BLOCK_COMMENT("} string_indexof DO3"); -+ } -+ -+ if (needle_con_cnt == -1 || needle_con_cnt == 1) { -+ Label DO1_LOOP; -+ -+ BLOCK_COMMENT("string_indexof DO1 {"); -+ bind(DO1); -+ (this->*needle_load_1chr)(ch1, Address(needle), noreg); -+ sub(result_tmp, haystack_len, 1); -+ mv(tmp3, result_tmp); -+ if (haystack_chr_shift) { -+ slli(tmp3, result_tmp, haystack_chr_shift); -+ } -+ add(haystack, haystack, tmp3); -+ neg(hlen_neg, tmp3); -+ -+ bind(DO1_LOOP); -+ add(tmp3, haystack, hlen_neg); -+ (this->*haystack_load_1chr)(ch2, Address(tmp3), noreg); -+ beq(ch1, ch2, MATCH); -+ add(hlen_neg, hlen_neg, haystack_chr_size); -+ blez(hlen_neg, DO1_LOOP); -+ BLOCK_COMMENT("} string_indexof DO1"); -+ } -+ -+ bind(NOMATCH); -+ mv(result, -1); -+ j(DONE); -+ -+ bind(MATCH); -+ srai(t0, hlen_neg, haystack_chr_shift); -+ add(result, result_tmp, t0); -+ -+ bind(DONE); -+} -+ -+// Compare strings. -+void MacroAssembler::string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2, -+ Register tmp3, int ae) -+{ -+ Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB, -+ DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT, -+ SHORT_LOOP_START, TAIL_CHECK, L; -+ -+ const int STUB_THRESHOLD = 64 + 8; -+ bool isLL = ae == StrIntrinsicNode::LL; -+ bool isLU = ae == StrIntrinsicNode::LU; -+ bool isUL = ae == StrIntrinsicNode::UL; -+ -+ bool str1_isL = isLL || isLU; -+ bool str2_isL = isLL || isUL; -+ -+ // for L strings, 1 byte for 1 character -+ // for U strings, 2 bytes for 1 character -+ int str1_chr_size = str1_isL ? 1 : 2; -+ int str2_chr_size = str2_isL ? 1 : 2; -+ int minCharsInWord = isLL ? wordSize : wordSize / 2; -+ -+ load_chr_insn str1_load_chr = str1_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -+ load_chr_insn str2_load_chr = str2_isL ? (load_chr_insn)&MacroAssembler::lbu : (load_chr_insn)&MacroAssembler::lhu; -+ -+ BLOCK_COMMENT("string_compare {"); -+ -+ // Bizzarely, the counts are passed in bytes, regardless of whether they -+ // are L or U strings, however the result is always in characters. -+ if (!str1_isL) { -+ sraiw(cnt1, cnt1, 1); -+ } -+ if (!str2_isL) { -+ sraiw(cnt2, cnt2, 1); -+ } -+ -+ // Compute the minimum of the string lengths and save the difference in result. -+ sub(result, cnt1, cnt2); -+ bgt(cnt1, cnt2, L); -+ mv(cnt2, cnt1); -+ bind(L); -+ -+ // A very short string -+ li(t0, minCharsInWord); -+ ble(cnt2, t0, SHORT_STRING); -+ -+ // Compare longwords -+ // load first parts of strings and finish initialization while loading -+ { -+ if (str1_isL == str2_isL) { // LL or UU -+ // load 8 bytes once to compare -+ ld(tmp1, Address(str1)); -+ beq(str1, str2, DONE); -+ ld(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ sub(cnt2, cnt2, minCharsInWord); -+ beqz(cnt2, TAIL_CHECK); -+ // convert cnt2 from characters to bytes -+ if (!str1_isL) { -+ slli(cnt2, cnt2, 1); -+ } -+ add(str2, str2, cnt2); -+ add(str1, str1, cnt2); -+ sub(cnt2, zr, cnt2); -+ } else if (isLU) { // LU case -+ lwu(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ addi(cnt2, cnt2, -4); -+ add(str1, str1, cnt2); -+ sub(cnt1, zr, cnt2); -+ slli(cnt2, cnt2, 1); -+ add(str2, str2, cnt2); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ sub(cnt2, zr, cnt2); -+ addi(cnt1, cnt1, 4); -+ } else { // UL case -+ ld(tmp1, Address(str1)); -+ lwu(tmp2, Address(str2)); -+ li(t0, STUB_THRESHOLD); -+ bge(cnt2, t0, STUB); -+ addi(cnt2, cnt2, -4); -+ slli(t0, cnt2, 1); -+ sub(cnt1, zr, t0); -+ add(str1, str1, t0); -+ add(str2, str2, cnt2); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ sub(cnt2, zr, cnt2); -+ addi(cnt1, cnt1, 8); -+ } -+ addi(cnt2, cnt2, isUL ? 4 : 8); -+ bgez(cnt2, TAIL); -+ xorr(tmp3, tmp1, tmp2); -+ bnez(tmp3, DIFFERENCE); -+ -+ // main loop -+ bind(NEXT_WORD); -+ if (str1_isL == str2_isL) { // LL or UU -+ add(t0, str1, cnt2); -+ ld(tmp1, Address(t0)); -+ add(t0, str2, cnt2); -+ ld(tmp2, Address(t0)); -+ addi(cnt2, cnt2, 8); -+ } else if (isLU) { // LU case -+ add(t0, str1, cnt1); -+ lwu(tmp1, Address(t0)); -+ add(t0, str2, cnt2); -+ ld(tmp2, Address(t0)); -+ addi(cnt1, cnt1, 4); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ addi(cnt2, cnt2, 8); -+ } else { // UL case -+ add(t0, str2, cnt2); -+ lwu(tmp2, Address(t0)); -+ add(t0, str1, cnt1); -+ ld(tmp1, Address(t0)); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ addi(cnt1, cnt1, 8); -+ addi(cnt2, cnt2, 4); -+ } -+ bgez(cnt2, TAIL); -+ -+ xorr(tmp3, tmp1, tmp2); -+ beqz(tmp3, NEXT_WORD); -+ j(DIFFERENCE); -+ bind(TAIL); -+ xorr(tmp3, tmp1, tmp2); -+ bnez(tmp3, DIFFERENCE); -+ // Last longword. In the case where length == 4 we compare the -+ // same longword twice, but that's still faster than another -+ // conditional branch. -+ if (str1_isL == str2_isL) { // LL or UU -+ ld(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ } else if (isLU) { // LU case -+ lwu(tmp1, Address(str1)); -+ ld(tmp2, Address(str2)); -+ inflate_lo32(tmp3, tmp1); -+ mv(tmp1, tmp3); -+ } else { // UL case -+ lwu(tmp2, Address(str2)); -+ ld(tmp1, Address(str1)); -+ inflate_lo32(tmp3, tmp2); -+ mv(tmp2, tmp3); -+ } -+ bind(TAIL_CHECK); -+ xorr(tmp3, tmp1, tmp2); -+ beqz(tmp3, DONE); -+ -+ // Find the first different characters in the longwords and -+ // compute their difference. -+ bind(DIFFERENCE); -+ ctzc_bit(result, tmp3, isLL); // count zero from lsb to msb -+ srl(tmp1, tmp1, result); -+ srl(tmp2, tmp2, result); -+ if (isLL) { -+ andi(tmp1, tmp1, 0xFF); -+ andi(tmp2, tmp2, 0xFF); -+ } else { -+ andi(tmp1, tmp1, 0xFFFF); -+ andi(tmp2, tmp2, 0xFFFF); -+ } -+ sub(result, tmp1, tmp2); -+ j(DONE); -+ } -+ -+ bind(STUB); -+ RuntimeAddress stub = NULL; -+ switch (ae) { -+ case StrIntrinsicNode::LL: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LL()); -+ break; -+ case StrIntrinsicNode::UU: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UU()); -+ break; -+ case StrIntrinsicNode::LU: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_LU()); -+ break; -+ case StrIntrinsicNode::UL: -+ stub = RuntimeAddress(StubRoutines::riscv::compare_long_string_UL()); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+ assert(stub.target() != NULL, "compare_long_string stub has not been generated"); -+ trampoline_call(stub); -+ j(DONE); -+ -+ bind(SHORT_STRING); -+ // Is the minimum length zero? -+ beqz(cnt2, DONE); -+ // arrange code to do most branches while loading and loading next characters -+ // while comparing previous -+ (this->*str1_load_chr)(tmp1, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST_INIT); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ j(SHORT_LOOP_START); -+ bind(SHORT_LOOP); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST); -+ bind(SHORT_LOOP_START); -+ (this->*str1_load_chr)(tmp2, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ (this->*str2_load_chr)(t0, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ bne(tmp1, cnt1, SHORT_LOOP_TAIL); -+ addi(cnt2, cnt2, -1); -+ beqz(cnt2, SHORT_LAST2); -+ (this->*str1_load_chr)(tmp1, Address(str1), t0); -+ addi(str1, str1, str1_chr_size); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ beq(tmp2, t0, SHORT_LOOP); -+ sub(result, tmp2, t0); -+ j(DONE); -+ bind(SHORT_LOOP_TAIL); -+ sub(result, tmp1, cnt1); -+ j(DONE); -+ bind(SHORT_LAST2); -+ beq(tmp2, t0, DONE); -+ sub(result, tmp2, t0); -+ -+ j(DONE); -+ bind(SHORT_LAST_INIT); -+ (this->*str2_load_chr)(cnt1, Address(str2), t0); -+ addi(str2, str2, str2_chr_size); -+ bind(SHORT_LAST); -+ beq(tmp1, cnt1, DONE); -+ sub(result, tmp1, cnt1); -+ -+ bind(DONE); -+ -+ BLOCK_COMMENT("} string_compare"); -+} -+ -+void MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3, -+ Register tmp4, Register tmp5, Register tmp6, Register result, -+ Register cnt1, int elem_size) { -+ Label DONE, SAME, NEXT_DWORD, SHORT, TAIL, TAIL2, IS_TMP5_ZR; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ Register cnt2 = tmp2; // cnt2 only used in array length compare -+ Register elem_per_word = tmp6; -+ int log_elem_size = exact_log2(elem_size); -+ int length_offset = arrayOopDesc::length_offset_in_bytes(); -+ int base_offset = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); -+ -+ assert(elem_size == 1 || elem_size == 2, "must be char or byte"); -+ assert_different_registers(a1, a2, result, cnt1, t0, t1, tmp3, tmp4, tmp5, tmp6); -+ li(elem_per_word, wordSize / elem_size); -+ -+ BLOCK_COMMENT("arrays_equals {"); -+ -+ // if (a1 == a2), return true -+ beq(a1, a2, SAME); -+ -+ mv(result, false); -+ beqz(a1, DONE); -+ beqz(a2, DONE); -+ lwu(cnt1, Address(a1, length_offset)); -+ lwu(cnt2, Address(a2, length_offset)); -+ bne(cnt2, cnt1, DONE); -+ beqz(cnt1, SAME); -+ -+ slli(tmp5, cnt1, 3 + log_elem_size); -+ sub(tmp5, zr, tmp5); -+ add(a1, a1, base_offset); -+ add(a2, a2, base_offset); -+ ld(tmp3, Address(a1, 0)); -+ ld(tmp4, Address(a2, 0)); -+ ble(cnt1, elem_per_word, SHORT); // short or same -+ -+ // Main 16 byte comparison loop with 2 exits -+ bind(NEXT_DWORD); { -+ ld(tmp1, Address(a1, wordSize)); -+ ld(tmp2, Address(a2, wordSize)); -+ sub(cnt1, cnt1, 2 * wordSize / elem_size); -+ blez(cnt1, TAIL); -+ bne(tmp3, tmp4, DONE); -+ ld(tmp3, Address(a1, 2 * wordSize)); -+ ld(tmp4, Address(a2, 2 * wordSize)); -+ add(a1, a1, 2 * wordSize); -+ add(a2, a2, 2 * wordSize); -+ ble(cnt1, elem_per_word, TAIL2); -+ } beq(tmp1, tmp2, NEXT_DWORD); -+ j(DONE); -+ -+ bind(TAIL); -+ xorr(tmp4, tmp3, tmp4); -+ xorr(tmp2, tmp1, tmp2); -+ sll(tmp2, tmp2, tmp5); -+ orr(tmp5, tmp4, tmp2); -+ j(IS_TMP5_ZR); -+ -+ bind(TAIL2); -+ bne(tmp1, tmp2, DONE); -+ -+ bind(SHORT); -+ xorr(tmp4, tmp3, tmp4); -+ sll(tmp5, tmp4, tmp5); -+ -+ bind(IS_TMP5_ZR); -+ bnez(tmp5, DONE); -+ -+ bind(SAME); -+ mv(result, true); -+ // That's it. -+ bind(DONE); -+ -+ BLOCK_COMMENT("} array_equals"); -+} -+ -+// Compare Strings -+ -+// For Strings we're passed the address of the first characters in a1 -+// and a2 and the length in cnt1. -+// elem_size is the element size in bytes: either 1 or 2. -+// There are two implementations. For arrays >= 8 bytes, all -+// comparisons (including the final one, which may overlap) are -+// performed 8 bytes at a time. For strings < 8 bytes, we compare a -+// halfword, then a short, and then a byte. -+ -+void MacroAssembler::string_equals(Register a1, Register a2, -+ Register result, Register cnt1, int elem_size) -+{ -+ Label SAME, DONE, SHORT, NEXT_WORD; -+ Register tmp1 = t0; -+ Register tmp2 = t1; -+ -+ assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte"); -+ assert_different_registers(a1, a2, result, cnt1, t0, t1); -+ -+ BLOCK_COMMENT("string_equals {"); -+ -+ mv(result, false); -+ -+ // Check for short strings, i.e. smaller than wordSize. -+ sub(cnt1, cnt1, wordSize); -+ bltz(cnt1, SHORT); -+ -+ // Main 8 byte comparison loop. -+ bind(NEXT_WORD); { -+ ld(tmp1, Address(a1, 0)); -+ add(a1, a1, wordSize); -+ ld(tmp2, Address(a2, 0)); -+ add(a2, a2, wordSize); -+ sub(cnt1, cnt1, wordSize); -+ bne(tmp1, tmp2, DONE); -+ } bgtz(cnt1, NEXT_WORD); -+ -+ // Last longword. In the case where length == 4 we compare the -+ // same longword twice, but that's still faster than another -+ // conditional branch. -+ // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when -+ // length == 4. -+ add(tmp1, a1, cnt1); -+ ld(tmp1, Address(tmp1, 0)); -+ add(tmp2, a2, cnt1); -+ ld(tmp2, Address(tmp2, 0)); -+ bne(tmp1, tmp2, DONE); -+ j(SAME); -+ -+ bind(SHORT); -+ Label TAIL03, TAIL01; -+ -+ // 0-7 bytes left. -+ andi(t0, cnt1, 4); -+ beqz(t0, TAIL03); -+ { -+ lwu(tmp1, Address(a1, 0)); -+ add(a1, a1, 4); -+ lwu(tmp2, Address(a2, 0)); -+ add(a2, a2, 4); -+ bne(tmp1, tmp2, DONE); -+ } -+ -+ bind(TAIL03); -+ // 0-3 bytes left. -+ andi(t0, cnt1, 2); -+ beqz(t0, TAIL01); -+ { -+ lhu(tmp1, Address(a1, 0)); -+ add(a1, a1, 2); -+ lhu(tmp2, Address(a2, 0)); -+ add(a2, a2, 2); -+ bne(tmp1, tmp2, DONE); -+ } -+ -+ bind(TAIL01); -+ if (elem_size == 1) { // Only needed when comparing 1-byte elements -+ // 0-1 bytes left. -+ andi(t0, cnt1, 1); -+ beqz(t0, SAME); -+ { -+ lbu(tmp1, a1, 0); -+ lbu(tmp2, a2, 0); -+ bne(tmp1, tmp2, DONE); -+ } -+ } -+ -+ // Arrays are equal. -+ bind(SAME); -+ mv(result, true); -+ -+ // That's it. -+ bind(DONE); -+ BLOCK_COMMENT("} string_equals"); -+} -+ -+typedef void (Assembler::*conditional_branch_insn)(Register op1, Register op2, Label& label, bool is_far); -+typedef void (MacroAssembler::*float_conditional_branch_insn)(FloatRegister op1, FloatRegister op2, Label& label, -+ bool is_far, bool is_unordered); -+ -+static conditional_branch_insn conditional_branches[] = -+{ -+ /* SHORT branches */ -+ (conditional_branch_insn)&Assembler::beq, -+ (conditional_branch_insn)&Assembler::bgt, -+ NULL, // BoolTest::overflow -+ (conditional_branch_insn)&Assembler::blt, -+ (conditional_branch_insn)&Assembler::bne, -+ (conditional_branch_insn)&Assembler::ble, -+ NULL, // BoolTest::no_overflow -+ (conditional_branch_insn)&Assembler::bge, -+ -+ /* UNSIGNED branches */ -+ (conditional_branch_insn)&Assembler::beq, -+ (conditional_branch_insn)&Assembler::bgtu, -+ NULL, -+ (conditional_branch_insn)&Assembler::bltu, -+ (conditional_branch_insn)&Assembler::bne, -+ (conditional_branch_insn)&Assembler::bleu, -+ NULL, -+ (conditional_branch_insn)&Assembler::bgeu -+}; -+ -+static float_conditional_branch_insn float_conditional_branches[] = -+{ -+ /* FLOAT SHORT branches */ -+ (float_conditional_branch_insn)&MacroAssembler::float_beq, -+ (float_conditional_branch_insn)&MacroAssembler::float_bgt, -+ NULL, // BoolTest::overflow -+ (float_conditional_branch_insn)&MacroAssembler::float_blt, -+ (float_conditional_branch_insn)&MacroAssembler::float_bne, -+ (float_conditional_branch_insn)&MacroAssembler::float_ble, -+ NULL, // BoolTest::no_overflow -+ (float_conditional_branch_insn)&MacroAssembler::float_bge, -+ -+ /* DOUBLE SHORT branches */ -+ (float_conditional_branch_insn)&MacroAssembler::double_beq, -+ (float_conditional_branch_insn)&MacroAssembler::double_bgt, -+ NULL, -+ (float_conditional_branch_insn)&MacroAssembler::double_blt, -+ (float_conditional_branch_insn)&MacroAssembler::double_bne, -+ (float_conditional_branch_insn)&MacroAssembler::double_ble, -+ NULL, -+ (float_conditional_branch_insn)&MacroAssembler::double_bge -+}; -+ -+void MacroAssembler::cmp_branch(int cmpFlag, Register op1, Register op2, Label& label, bool is_far) { -+ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(conditional_branches) / sizeof(conditional_branches[0])), -+ "invalid conditional branch index"); -+ (this->*conditional_branches[cmpFlag])(op1, op2, label, is_far); -+} -+ -+// This is a function should only be used by C2. Flip the unordered when unordered-greater, C2 would use -+// unordered-lesser instead of unordered-greater. Finally, commute the result bits at function do_one_bytecode(). -+void MacroAssembler::float_cmp_branch(int cmpFlag, FloatRegister op1, FloatRegister op2, Label& label, bool is_far) { -+ assert(cmpFlag >= 0 && cmpFlag < (int)(sizeof(float_conditional_branches) / sizeof(float_conditional_branches[0])), -+ "invalid float conditional branch index"); -+ int booltest_flag = cmpFlag & ~(MacroAssembler::double_branch_mask); -+ (this->*float_conditional_branches[cmpFlag])(op1, op2, label, is_far, -+ (booltest_flag == (BoolTest::ge) || booltest_flag == (BoolTest::gt)) ? false : true); -+} -+ -+void MacroAssembler::enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -+ switch (cmpFlag) { -+ case BoolTest::eq: -+ case BoolTest::le: -+ beqz(op1, L, is_far); -+ break; -+ case BoolTest::ne: -+ case BoolTest::gt: -+ bnez(op1, L, is_far); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+} -+ -+void MacroAssembler::enc_cmpEqNe_imm0_branch(int cmpFlag, Register op1, Label& L, bool is_far) { -+ switch (cmpFlag) { -+ case BoolTest::eq: -+ beqz(op1, L, is_far); -+ break; -+ case BoolTest::ne: -+ bnez(op1, L, is_far); -+ break; -+ default: -+ ShouldNotReachHere(); -+ } -+} -+ -+void MacroAssembler::enc_cmove(int cmpFlag, Register op1, Register op2, Register dst, Register src) { -+ Label L; -+ cmp_branch(cmpFlag ^ (1 << neg_cond_bits), op1, op2, L); -+ mv(dst, src); -+ bind(L); -+} -+ -+// Set dst to NaN if any NaN input. -+void MacroAssembler::minmax_FD(FloatRegister dst, FloatRegister src1, FloatRegister src2, -+ bool is_double, bool is_min) { -+ assert_different_registers(dst, src1, src2); -+ -+ Label Done; -+ fsflags(zr); -+ if (is_double) { -+ is_min ? fmin_d(dst, src1, src2) -+ : fmax_d(dst, src1, src2); -+ // Checking NaNs -+ flt_d(zr, src1, src2); -+ } else { -+ is_min ? fmin_s(dst, src1, src2) -+ : fmax_s(dst, src1, src2); -+ // Checking NaNs -+ flt_s(zr, src1, src2); -+ } -+ -+ frflags(t0); -+ beqz(t0, Done); -+ -+ // In case of NaNs -+ is_double ? fadd_d(dst, src1, src2) -+ : fadd_s(dst, src1, src2); -+ -+ bind(Done); -+} -+ -+#endif // COMPILER2 -+ -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index c6b71bdbc3c..2ef28771e2e 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -851,6 +851,109 @@ class MacroAssembler: public Assembler { - void load_reserved(Register addr, enum operand_size size, Assembler::Aqrl acquire); - void store_conditional(Register addr, Register new_val, enum operand_size size, Assembler::Aqrl release); - -+public: -+ void string_compare(Register str1, Register str2, -+ Register cnt1, Register cnt2, Register result, -+ Register tmp1, Register tmp2, Register tmp3, -+ int ae); -+ -+ void string_indexof_char_short(Register str1, Register cnt1, -+ Register ch, Register result, -+ bool isL); -+ -+ void string_indexof_char(Register str1, Register cnt1, -+ Register ch, Register result, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ bool isL); -+ -+ void string_indexof(Register str1, Register str2, -+ Register cnt1, Register cnt2, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, int ae); -+ -+ void string_indexof_linearscan(Register haystack, Register needle, -+ Register haystack_len, Register needle_len, -+ Register tmp1, Register tmp2, -+ Register tmp3, Register tmp4, -+ int needle_con_cnt, Register result, int ae); -+ -+ void arrays_equals(Register r1, Register r2, -+ Register tmp3, Register tmp4, -+ Register tmp5, Register tmp6, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ void string_equals(Register r1, Register r2, -+ Register result, Register cnt1, -+ int elem_size); -+ -+ // refer to conditional_branches and float_conditional_branches -+ static const int bool_test_bits = 3; -+ static const int neg_cond_bits = 2; -+ static const int unsigned_branch_mask = 1 << bool_test_bits; -+ static const int double_branch_mask = 1 << bool_test_bits; -+ -+ // cmp -+ void cmp_branch(int cmpFlag, -+ Register op1, Register op2, -+ Label& label, bool is_far = false); -+ -+ void float_cmp_branch(int cmpFlag, -+ FloatRegister op1, FloatRegister op2, -+ Label& label, bool is_far = false); -+ -+ void enc_cmpUEqNeLeGt_imm0_branch(int cmpFlag, Register op, -+ Label& L, bool is_far = false); -+ -+ void enc_cmpEqNe_imm0_branch(int cmpFlag, Register op, -+ Label& L, bool is_far = false); -+ -+ void enc_cmove(int cmpFlag, -+ Register op1, Register op2, -+ Register dst, Register src); -+ -+ void spill(Register r, bool is64, int offset) { -+ is64 ? sd(r, Address(sp, offset)) -+ : sw(r, Address(sp, offset)); -+ } -+ -+ void spill(FloatRegister f, bool is64, int offset) { -+ is64 ? fsd(f, Address(sp, offset)) -+ : fsw(f, Address(sp, offset)); -+ } -+ -+ void spill(VectorRegister v, int offset) { -+ add(t0, sp, offset); -+ vs1r_v(v, t0); -+ } -+ -+ void unspill(Register r, bool is64, int offset) { -+ is64 ? ld(r, Address(sp, offset)) -+ : lw(r, Address(sp, offset)); -+ } -+ -+ void unspillu(Register r, bool is64, int offset) { -+ is64 ? ld(r, Address(sp, offset)) -+ : lwu(r, Address(sp, offset)); -+ } -+ -+ void unspill(FloatRegister f, bool is64, int offset) { -+ is64 ? fld(f, Address(sp, offset)) -+ : flw(f, Address(sp, offset)); -+ } -+ -+ void unspill(VectorRegister v, int offset) { -+ add(t0, sp, offset); -+ vl1r_v(v, t0); -+ } -+ -+ void minmax_FD(FloatRegister dst, -+ FloatRegister src1, FloatRegister src2, -+ bool is_double, bool is_min); -+ - }; - - #ifdef ASSERT -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 13546ab328b..2e7eed8fb52 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -997,7 +997,7 @@ void MachBreakpointNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - #endif - - void MachBreakpointNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - __ ebreak(); - } -@@ -1015,7 +1015,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - #endif - - void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc*) const { -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); // nops shall be 2-byte under RVC for alignment purposes. - for (int i = 0; i < _count; i++) { - __ nop(); -@@ -1074,7 +1074,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - assert_cond(ra_ != NULL); - Compile* C = ra_->C; -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - - // n.b. frame size includes space for return pc and fp - const int framesize = C->output()->frame_size_in_bytes(); -@@ -1150,7 +1150,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - assert_cond(ra_ != NULL); - Compile* C = ra_->C; -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - assert_cond(C != NULL); - int framesize = C->output()->frame_size_in_bytes(); - -@@ -1251,7 +1251,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo - int dst_offset = ra_->reg2offset(dst_lo); - - if (cbuf != NULL) { -- C2_MacroAssembler _masm(cbuf); -+ MacroAssembler _masm(cbuf); - Assembler::CompressibleRegion cr(&_masm); - switch (src_lo_rc) { - case rc_int: -@@ -1371,7 +1371,7 @@ void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - #endif - - void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - - assert_cond(ra_ != NULL); - int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); -@@ -1422,7 +1422,7 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const - void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const - { - // This is the unverified entry point. -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - - Label skip; - __ cmp_klass(j_rarg0, t1, t0, skip); -@@ -1449,7 +1449,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) - // j #exception_blob_entry_point - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - address base = __ start_a_stub(size_exception_handler()); - if (base == NULL) { - ciEnv::current()->record_failure("CodeCache is full"); -@@ -1467,7 +1467,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) - { - // Note that the code buffer's insts_mark is always relative to insts. - // That's why we must use the macroassembler to generate a handler. -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - address base = __ start_a_stub(size_deopt_handler()); - if (base == NULL) { - ciEnv::current()->record_failure("CodeCache is full"); -@@ -1848,7 +1848,7 @@ encode %{ - // BEGIN Non-volatile memory access - - enc_class riscv_enc_li_imm(iRegIorL dst, immIorL src) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - int64_t con = (int64_t)$src$$constant; - Register dst_reg = as_Register($dst$$reg); -@@ -1856,7 +1856,7 @@ encode %{ - %} - - enc_class riscv_enc_mov_p(iRegP dst, immP src) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - address con = (address)$src$$constant; - if (con == NULL || con == (address)1) { -@@ -1875,7 +1875,7 @@ encode %{ - %} - - enc_class riscv_enc_mov_p1(iRegP dst) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - Register dst_reg = as_Register($dst$$reg); - __ li(dst_reg, 1); -@@ -1893,12 +1893,12 @@ encode %{ - %} - - enc_class riscv_enc_mov_byte_map_base(iRegP dst) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ load_byte_map_base($dst$$Register); - %} - - enc_class riscv_enc_mov_n(iRegN dst, immN src) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - address con = (address)$src$$constant; - if (con == NULL) { -@@ -1911,13 +1911,13 @@ encode %{ - %} - - enc_class riscv_enc_mov_zero(iRegNorP dst) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - __ mv(dst_reg, zr); - %} - - enc_class riscv_enc_mov_nk(iRegN dst, immNKlass src) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - address con = (address)$src$$constant; - if (con == NULL) { -@@ -1930,42 +1930,42 @@ encode %{ - %} - - enc_class riscv_enc_cmpxchgw(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, - /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); - %} - - enc_class riscv_enc_cmpxchgn(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, - /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); - %} - - enc_class riscv_enc_cmpxchg(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, - /*acquire*/ Assembler::relaxed, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); - %} - - enc_class riscv_enc_cmpxchgw_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int32, - /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); - %} - - enc_class riscv_enc_cmpxchgn_acq(iRegINoSp res, memory mem, iRegINoSp oldval, iRegINoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::uint32, - /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); - %} - - enc_class riscv_enc_cmpxchg_acq(iRegINoSp res, memory mem, iRegLNoSp oldval, iRegLNoSp newval) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ cmpxchg(as_Register($mem$$base), $oldval$$Register, $newval$$Register, Assembler::int64, - /*acquire*/ Assembler::aq, /*release*/ Assembler::rl, $res$$Register, - /*result as bool*/ true); -@@ -1974,13 +1974,13 @@ encode %{ - // compare and branch instruction encodings - - enc_class riscv_enc_j(label lbl) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Label* L = $lbl$$label; - __ j(*L); - %} - - enc_class riscv_enc_far_cmpULtGe_imm0_branch(cmpOpULtGe cmp, iRegIorL op1, label lbl) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Label* L = $lbl$$label; - switch ($cmp$$cmpcode) { - case(BoolTest::ge): -@@ -2004,7 +2004,7 @@ encode %{ - - Label miss; - Label done; -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ check_klass_subtype_slow_path(sub_reg, super_reg, temp_reg, result_reg, - NULL, &miss); - if ($primary) { -@@ -2023,7 +2023,7 @@ encode %{ - %} - - enc_class riscv_enc_java_static_call(method meth) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - - address addr = (address)$meth$$method; - address call = NULL; -@@ -2055,7 +2055,7 @@ encode %{ - %} - - enc_class riscv_enc_java_dynamic_call(method meth) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - int method_index = resolved_method_index(cbuf); - address call = __ ic_call((address)$meth$$method, method_index); - if (call == NULL) { -@@ -2065,7 +2065,7 @@ encode %{ - %} - - enc_class riscv_enc_call_epilog() %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - if (VerifyStackAtCalls) { - // Check that stack depth is unchanged: find majik cookie on stack - __ call_Unimplemented(); -@@ -2073,7 +2073,7 @@ encode %{ - %} - - enc_class riscv_enc_java_to_runtime(method meth) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - - // some calls to generated routines (arraycopy code) are scheduled - // by C2 as runtime calls. if so we can call them using a jr (they -@@ -2102,7 +2102,7 @@ encode %{ - - // using the cr register as the bool result: 0 for success; others failed. - enc_class riscv_enc_fast_lock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register flag = t1; - Register oop = as_Register($object$$reg); - Register box = as_Register($box$$reg); -@@ -2189,7 +2189,7 @@ encode %{ - - // using cr flag to indicate the fast_unlock result: 0 for success; others failed. - enc_class riscv_enc_fast_unlock(iRegP object, iRegP box, iRegP tmp1, iRegP tmp2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register flag = t1; - Register oop = as_Register($object$$reg); - Register box = as_Register($box$$reg); -@@ -2262,7 +2262,7 @@ encode %{ - // arithmetic encodings - - enc_class riscv_enc_divw(iRegI dst, iRegI src1, iRegI src2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - Register src1_reg = as_Register($src1$$reg); - Register src2_reg = as_Register($src2$$reg); -@@ -2270,7 +2270,7 @@ encode %{ - %} - - enc_class riscv_enc_div(iRegI dst, iRegI src1, iRegI src2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - Register src1_reg = as_Register($src1$$reg); - Register src2_reg = as_Register($src2$$reg); -@@ -2278,7 +2278,7 @@ encode %{ - %} - - enc_class riscv_enc_modw(iRegI dst, iRegI src1, iRegI src2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - Register src1_reg = as_Register($src1$$reg); - Register src2_reg = as_Register($src2$$reg); -@@ -2286,7 +2286,7 @@ encode %{ - %} - - enc_class riscv_enc_mod(iRegI dst, iRegI src1, iRegI src2) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Register dst_reg = as_Register($dst$$reg); - Register src1_reg = as_Register($src1$$reg); - Register src2_reg = as_Register($src2$$reg); -@@ -2294,14 +2294,14 @@ encode %{ - %} - - enc_class riscv_enc_tail_call(iRegP jump_target) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - Register target_reg = as_Register($jump_target$$reg); - __ jr(target_reg); - %} - - enc_class riscv_enc_tail_jmp(iRegP jump_target) %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - Register target_reg = as_Register($jump_target$$reg); - // exception oop should be in x10 -@@ -2312,12 +2312,12 @@ encode %{ - %} - - enc_class riscv_enc_rethrow() %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - __ far_jump(RuntimeAddress(OptoRuntime::rethrow_stub())); - %} - - enc_class riscv_enc_ret() %{ -- C2_MacroAssembler _masm(&cbuf); -+ MacroAssembler _masm(&cbuf); - Assembler::CompressibleRegion cr(&_masm); - __ ret(); - %} -@@ -8506,7 +8506,7 @@ instruct cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8526,7 +8526,7 @@ instruct cmpU_loop(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpU_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8585,7 +8585,7 @@ instruct cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8604,7 +8604,7 @@ instruct cmpUL_loop(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpUL_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8625,7 +8625,7 @@ instruct cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8645,7 +8645,7 @@ instruct cmpP_loop(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpP_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8666,7 +8666,7 @@ instruct cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8686,7 +8686,7 @@ instruct cmpN_loop(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) - format %{ "b$cmp $op1, $op2, $lbl\t#@cmpN_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label)); - %} - -@@ -8741,7 +8741,7 @@ instruct cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - format %{ "double_b$cmp $op1, $op2\t#@cmpD_branch"%} - - ins_encode %{ -- __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -+ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), - as_FloatRegister($op2$$reg), *($lbl$$label)); - %} - -@@ -8759,7 +8759,7 @@ instruct cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - format %{ "double_b$cmp $op1, $op2\t#@cmpD_loop"%} - - ins_encode %{ -- __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -+ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), - as_FloatRegister($op2$$reg), *($lbl$$label)); - %} - -@@ -9080,7 +9080,7 @@ instruct far_cmpU_branch(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) %{ - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9095,7 +9095,7 @@ instruct far_cmpU_loop(cmpOpU cmp, iRegI op1, iRegI op2, label lbl) %{ - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpU_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9138,7 +9138,7 @@ instruct far_cmpUL_branch(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) %{ - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9153,7 +9153,7 @@ instruct far_cmpUL_loop(cmpOpU cmp, iRegL op1, iRegL op2, label lbl) %{ - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpUL_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9171,7 +9171,7 @@ instruct far_cmpP_branch(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9189,7 +9189,7 @@ instruct far_cmpP_loop(cmpOpU cmp, iRegP op1, iRegP op2, label lbl) - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpP_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9207,7 +9207,7 @@ instruct far_cmpN_branch(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_branch" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9225,7 +9225,7 @@ instruct far_cmpN_loop(cmpOpU cmp, iRegN op1, iRegN op2, label lbl) - format %{ "far_b$cmp $op1, $op2, $lbl\t#@far_cmpN_loop" %} - - ins_encode %{ -- __ cmp_branch($cmp$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), -+ __ cmp_branch($cmp$$cmpcode | MacroAssembler::unsigned_branch_mask, as_Register($op1$$reg), - as_Register($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9276,7 +9276,7 @@ instruct far_cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_branch"%} - - ins_encode %{ -- __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -+ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), - as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9292,7 +9292,7 @@ instruct far_cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_loop"%} - - ins_encode %{ -- __ float_cmp_branch($cmp$$cmpcode | C2_MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -+ __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), - as_FloatRegister($op2$$reg), *($lbl$$label), /* is_far */ true); - %} - -@@ -9616,7 +9616,7 @@ instruct cmovI_cmpU(iRegINoSp dst, iRegI src, iRegI op1, iRegI op2, cmpOpU cop) - %} - - ins_encode %{ -- __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, -+ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, - as_Register($op1$$reg), as_Register($op2$$reg), - as_Register($dst$$reg), as_Register($src$$reg)); - %} -@@ -9673,7 +9673,7 @@ instruct cmovL_cmpUL(iRegLNoSp dst, iRegL src, iRegL op1, iRegL op2, cmpOpU cop) - %} - - ins_encode %{ -- __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, -+ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, - as_Register($op1$$reg), as_Register($op2$$reg), - as_Register($dst$$reg), as_Register($src$$reg)); - %} -@@ -9691,7 +9691,7 @@ instruct cmovI_cmpUL(iRegINoSp dst, iRegI src, iRegL op1, iRegL op2, cmpOpU cop) - %} - - ins_encode %{ -- __ enc_cmove($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, -+ __ enc_cmove($cop$$cmpcode | MacroAssembler::unsigned_branch_mask, - as_Register($op1$$reg), as_Register($op2$$reg), - as_Register($dst$$reg), as_Register($src$$reg)); - %} - -From 115cd21290080b157d0ca8b7080e66ebd814fbdb Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:15:18 +0800 -Subject: [PATCH 091/140] Revert JDK-8222297: IRT_ENTRY/IRT_LEAF etc are the - same as JRT && JDK-8263709: Cleanup THREAD/TRAPS/CHECK usage in JRT_ENTRY - routines - ---- - src/hotspot/cpu/riscv/interpreterRT_riscv.cpp | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp -index d93530d8564..776b0787238 100644 ---- a/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp -+++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp -@@ -278,12 +278,12 @@ class SlowSignatureHandler - }; - - --JRT_ENTRY(address, -- InterpreterRuntime::slow_signature_handler(JavaThread* current, -+IRT_ENTRY(address, -+ InterpreterRuntime::slow_signature_handler(JavaThread* thread, - Method* method, - intptr_t* from, - intptr_t* to)) -- methodHandle m(current, (Method*)method); -+ methodHandle m(thread, (Method*)method); - assert(m->is_native(), "sanity check"); - - // handle arguments -@@ -292,4 +292,4 @@ JRT_ENTRY(address, - - // return result handler - return Interpreter::result_handler(m->result_type()); --JRT_END -+IRT_END - -From 6cbf43d5f095aef93ef0bf595f51019a03cc1989 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:20:06 +0800 -Subject: [PATCH 092/140] Revert JDK-8245289: Clean up offset code in - JavaClasses - ---- - src/hotspot/cpu/riscv/methodHandles_riscv.cpp | 18 +++++++++--------- - .../templateInterpreterGenerator_riscv.cpp | 2 +- - 2 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -index 4442b5991b1..e070b8096a6 100644 ---- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -53,7 +53,7 @@ void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_ - verify_klass(_masm, klass_reg, VM_CLASS_ID(java_lang_Class), - "MH argument is a Class"); - } -- __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset())); -+ __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset_in_bytes())); - } - - #ifdef ASSERT -@@ -140,13 +140,13 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, - - // Load the invoker, as MH -> MH.form -> LF.vmentry - __ verify_oop(recv); -- __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset())), temp2); -+ __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), temp2); - __ verify_oop(method_temp); -- __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset())), temp2); -+ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), temp2); - __ verify_oop(method_temp); -- __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset())), temp2); -+ __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), temp2); - __ verify_oop(method_temp); -- __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())), noreg, noreg); -+ __ access_load_at(T_ADDRESS, IN_HEAP, method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())), noreg, noreg); - - if (VerifyMethodHandles && !for_compiler_entry) { - // make sure recv is already on stack -@@ -284,10 +284,10 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, - "MemberName required for invokeVirtual etc."); - } - -- Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset())); -- Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset())); -- Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset())); -- Address vmtarget_method( xmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset())); -+ Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); -+ Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); -+ Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); -+ Address vmtarget_method( xmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); - - Register temp1_recv_klass = temp1; - if (iid != vmIntrinsics::_linkToStatic) { -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index 8aea4eca048..ce6166030b4 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -894,7 +894,7 @@ address TemplateInterpreterGenerator::generate_Reference_get_entry(void) { - - address entry = __ pc(); - -- const int referent_offset = java_lang_ref_Reference::referent_offset(); -+ const int referent_offset = java_lang_ref_Reference::referent_offset; - guarantee(referent_offset > 0, "referent offset not initialized"); - - Label slow_path; - -From 8c9b9f4246f4ede3c31f59749f9d4bc625f106b3 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:30:35 +0800 -Subject: [PATCH 093/140] Revert JDK-8242629: Remove references to deprecated - java.util.Observer and Observable - ---- - .../runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java | 2 -- - .../classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java | 2 -- - .../sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java | 2 -- - 3 files changed, 6 deletions(-) - -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java -index f2e224f28ee..5c2b6e0e3ea 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/linux_riscv64/LinuxRISCV64JavaThreadPDAccess.java -@@ -34,8 +34,6 @@ - import sun.jvm.hotspot.runtime.riscv64.*; - import sun.jvm.hotspot.types.*; - import sun.jvm.hotspot.utilities.*; --import sun.jvm.hotspot.utilities.Observable; --import sun.jvm.hotspot.utilities.Observer; - - public class LinuxRISCV64JavaThreadPDAccess implements JavaThreadPDAccess { - private static AddressField lastJavaFPField; -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java -index df280005d72..e372bc5f7be 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java -@@ -34,8 +34,6 @@ - import sun.jvm.hotspot.runtime.*; - import sun.jvm.hotspot.types.*; - import sun.jvm.hotspot.utilities.*; --import sun.jvm.hotspot.utilities.Observable; --import sun.jvm.hotspot.utilities.Observer; - - /** Specialization of and implementation of abstract methods of the - Frame class for the riscv64 family of CPUs. */ -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java -index d0ad2b559a6..850758a7ed4 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64JavaCallWrapper.java -@@ -31,8 +31,6 @@ - import sun.jvm.hotspot.types.*; - import sun.jvm.hotspot.runtime.*; - import sun.jvm.hotspot.utilities.*; --import sun.jvm.hotspot.utilities.Observable; --import sun.jvm.hotspot.utilities.Observer; - - public class RISCV64JavaCallWrapper extends JavaCallWrapper { - private static AddressField lastJavaFPField; - -From 43f2a4fec6b4922fa8c187deda310ad636aeed2e Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:33:56 +0800 -Subject: [PATCH 094/140] Revert JDK-8256155: Allow multiple large page sizes - to be used on Linux - ---- - src/hotspot/os/linux/os_linux.cpp | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp -index 6f75e623a9a..7fc9588301b 100644 ---- a/src/hotspot/os/linux/os_linux.cpp -+++ b/src/hotspot/os/linux/os_linux.cpp -@@ -4078,7 +4078,8 @@ size_t os::Linux::find_large_page_size() { - IA64_ONLY(256 * M) - PPC_ONLY(4 * M) - S390_ONLY(1 * M) -- SPARC_ONLY(4 * M); -+ SPARC_ONLY(4 * M) -+ RISCV64_ONLY(2 * M); - #endif // ZERO - - FILE *fp = fopen("/proc/meminfo", "r"); - -From a93191be0155882a0f4d92bba4de9fdf4f508a4a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:38:53 +0800 -Subject: [PATCH 095/140] Revert JDK-8252204: AArch64: Implement SHA3 - accelerator/intrinsic - ---- - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 5 ----- - 1 file changed, 5 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index d4b79162d84..50ee7edb708 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -82,11 +82,6 @@ void VM_Version::initialize() { - FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); - } - -- if (UseSHA3Intrinsics) { -- warning("Intrinsics for SHA3-224, SHA3-256, SHA3-384 and SHA3-512 crypto hash functions not available on this CPU."); -- FLAG_SET_DEFAULT(UseSHA3Intrinsics, false); -- } -- - if (UseCRC32Intrinsics) { - warning("CRC32 intrinsics are not available on this CPU."); - FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); - -From 29acd4f1bb99e856418f7d9d3da4f205812b1663 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:43:23 +0800 -Subject: [PATCH 096/140] Revert JDK-8253717: Relocate stack overflow code out - of thread.hpp/cpp && JDK-8255766: Fix linux+arm64 build after 8254072 - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 4 ++-- - src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp | 2 +- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index d175a62aeeb..d94074b4a3c 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1666,7 +1666,7 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) { - // was post-decremented.) Skip this address by starting at i=1, and - // touch a few more pages below. N.B. It is important to touch all - // the way down to and including i=StackShadowPages. -- for (int i = 0; i < (int)(StackOverflow::stack_shadow_zone_size() / os::vm_page_size()) - 1; i++) { -+ for (int i = 0; i < (int)(JavaThread::stack_shadow_zone_size() / os::vm_page_size()) - 1; i++) { - // this could be any sized move but this is can be a debugging crumb - // so the bigger the better. - sub(tmp, tmp, os::vm_page_size()); -diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -index ae414224c5b..dc3ac548d73 100644 ---- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -+++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -1252,7 +1252,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - __ nop(); - - // Generate stack overflow check -- __ bang_stack_with_offset(checked_cast(StackOverflow::stack_shadow_zone_size())); -+ __ bang_stack_with_offset((int)JavaThread::stack_shadow_zone_size()); - - // Generate a new frame for the wrapper. - __ enter(); -@@ -1551,7 +1551,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, - Label reguard; - Label reguard_done; - __ lbu(t0, Address(xthread, JavaThread::stack_guard_state_offset())); -- __ mv(t1, StackOverflow::stack_guard_yellow_reserved_disabled); -+ __ mv(t1, JavaThread::stack_guard_yellow_reserved_disabled); - __ beq(t0, t1, reguard); - __ bind(reguard_done); - -diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -index ce6166030b4..e639fa7e12f 100644 ---- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp -@@ -1248,7 +1248,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { - { - Label no_reguard; - __ lwu(t0, Address(xthread, in_bytes(JavaThread::stack_guard_state_offset()))); -- __ addi(t1, zr, (u1)StackOverflow::stack_guard_yellow_reserved_disabled); -+ __ addi(t1, zr, (u1)JavaThread::stack_guard_yellow_reserved_disabled); - __ bne(t0, t1, no_reguard); - - __ pusha(); // only save smashed registers - -From 6fa17c662dd2488108809e77dcff921bb475813c Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:50:51 +0800 -Subject: [PATCH 097/140] Revert JDK-8258459: Decouple gc_globals.hpp from - globals.hpp - ---- - src/hotspot/cpu/riscv/templateTable_riscv.cpp | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -index 1f4409a9c9a..84b1afc7dc6 100644 ---- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp -+++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -28,7 +28,6 @@ - #include "asm/macroAssembler.inline.hpp" - #include "gc/shared/barrierSetAssembler.hpp" - #include "gc/shared/collectedHeap.hpp" --#include "gc/shared/tlab_globals.hpp" - #include "interpreter/interp_masm.hpp" - #include "interpreter/interpreter.hpp" - #include "interpreter/interpreterRuntime.hpp" - -From bcc26e749ccc20db5a4ba51c2cf8740a908a8a74 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 16:56:58 +0800 -Subject: [PATCH 098/140] Revert JDK-8223136: Move compressed oops functions to - CompressedOops class - ---- - .../cpu/riscv/macroAssembler_riscv.cpp | 64 +++++++++---------- - .../cpu/riscv/macroAssembler_riscv.hpp | 1 - - src/hotspot/cpu/riscv/riscv.ad | 10 +-- - 3 files changed, 37 insertions(+), 38 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index d94074b4a3c..becc1656358 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1318,10 +1318,10 @@ int MacroAssembler::patch_oop(address insn_addr, address o) { - void MacroAssembler::reinit_heapbase() { - if (UseCompressedOops) { - if (Universe::is_fully_initialized()) { -- mv(xheapbase, CompressedOops::ptrs_base()); -+ mv(xheapbase, Universe::narrow_ptrs_base()); - } else { - int32_t offset = 0; -- la_patchable(xheapbase, ExternalAddress((address)CompressedOops::ptrs_base_addr()), offset); -+ la_patchable(xheapbase, ExternalAddress((address)Universe::narrow_ptrs_base_addr()), offset); - ld(xheapbase, Address(xheapbase, offset)); - } - } -@@ -1596,8 +1596,8 @@ void MacroAssembler::orptr(Address adr, RegisterOrConstant src, Register tmp1, R - void MacroAssembler::cmp_klass(Register oop, Register trial_klass, Register tmp, Label &L) { - if (UseCompressedClassPointers) { - lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes())); -- if (CompressedKlassPointers::base() == NULL) { -- slli(tmp, tmp, CompressedKlassPointers::shift()); -+ if (Universe::narrow_klass_base() == NULL) { -+ slli(tmp, tmp, Universe::narrow_klass_shift()); - beq(trial_klass, tmp, L); - return; - } -@@ -1745,9 +1745,9 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, - // Algorithm must match CompressedOops::encode. - void MacroAssembler::encode_heap_oop(Register d, Register s) { - verify_oop(s, "broken oop in encode_heap_oop"); -- if (CompressedOops::base() == NULL) { -- if (CompressedOops::shift() != 0) { -- assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); -+ if (Universe::narrow_oop_base() == NULL) { -+ if (Universe::narrow_oop_shift() != 0) { -+ assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - srli(d, s, LogMinObjAlignmentInBytes); - } else { - mv(d, s); -@@ -1758,9 +1758,9 @@ void MacroAssembler::encode_heap_oop(Register d, Register s) { - bgez(d, notNull); - mv(d, zr); - bind(notNull); -- if (CompressedOops::shift() != 0) { -- assert (LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); -- srli(d, d, CompressedOops::shift()); -+ if (Universe::narrow_oop_shift() != 0) { -+ assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); -+ srli(d, d, Universe::narrow_oop_shift()); - } - } - } -@@ -1799,9 +1799,9 @@ void MacroAssembler::decode_klass_not_null(Register r) { - void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) { - assert(UseCompressedClassPointers, "should only be used for compressed headers"); - -- if (CompressedKlassPointers::base() == NULL) { -- if (CompressedKlassPointers::shift() != 0) { -- assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); -+ if (Universe::narrow_klass_base() == NULL) { -+ if (Universe::narrow_klass_shift() != 0) { -+ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - slli(dst, src, LogKlassAlignmentInBytes); - } else { - mv(dst, src); -@@ -1815,10 +1815,10 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register - } - - assert_different_registers(src, xbase); -- li(xbase, (uintptr_t)CompressedKlassPointers::base()); -+ li(xbase, (uintptr_t)Universe::narrow_klass_base()); - -- if (CompressedKlassPointers::shift() != 0) { -- assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); -+ if (Universe::narrow_klass_shift() != 0) { -+ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - assert_different_registers(t0, xbase); - shadd(dst, src, xbase, t0, LogKlassAlignmentInBytes); - } else { -@@ -1835,9 +1835,9 @@ void MacroAssembler::encode_klass_not_null(Register r) { - void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) { - assert(UseCompressedClassPointers, "should only be used for compressed headers"); - -- if (CompressedKlassPointers::base() == NULL) { -- if (CompressedKlassPointers::shift() != 0) { -- assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); -+ if (Universe::narrow_klass_base() == NULL) { -+ if (Universe::narrow_klass_shift() != 0) { -+ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - srli(dst, src, LogKlassAlignmentInBytes); - } else { - mv(dst, src); -@@ -1845,8 +1845,8 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register - return; - } - -- if (((uint64_t)(uintptr_t)CompressedKlassPointers::base() & 0xffffffff) == 0 && -- CompressedKlassPointers::shift() == 0) { -+ if (((uint64_t)(uintptr_t)Universe::narrow_klass_base() & 0xffffffff) == 0 && -+ Universe::narrow_klass_shift() == 0) { - zero_extend(dst, src, 32); - return; - } -@@ -1857,10 +1857,10 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register - } - - assert_different_registers(src, xbase); -- li(xbase, (intptr_t)CompressedKlassPointers::base()); -+ li(xbase, (intptr_t)Universe::narrow_klass_base()); - sub(dst, src, xbase); -- if (CompressedKlassPointers::shift() != 0) { -- assert(LogKlassAlignmentInBytes == CompressedKlassPointers::shift(), "decode alg wrong"); -+ if (Universe::narrow_klass_shift() != 0) { -+ assert(LogKlassAlignmentInBytes == Universe::narrow_klass_shift(), "decode alg wrong"); - srli(dst, dst, LogKlassAlignmentInBytes); - } - if (xbase == xheapbase) { -@@ -1878,22 +1878,22 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) { - // Cannot assert, unverified entry point counts instructions (see .ad file) - // vtableStubs also counts instructions in pd_code_size_limit. - // Also do not verify_oop as this is called by verify_oop. -- if (CompressedOops::shift() != 0) { -- assert(LogMinObjAlignmentInBytes == CompressedOops::shift(), "decode alg wrong"); -+ if (Universe::narrow_oop_shift() != 0) { -+ assert(LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong"); - slli(dst, src, LogMinObjAlignmentInBytes); -- if (CompressedOops::base() != NULL) { -+ if (Universe::narrow_oop_base() != NULL) { - add(dst, xheapbase, dst); - } - } else { -- assert(CompressedOops::base() == NULL, "sanity"); -+ assert(Universe::narrow_oop_base() == NULL, "sanity"); - mv(dst, src); - } - } - - void MacroAssembler::decode_heap_oop(Register d, Register s) { -- if (CompressedOops::base() == NULL) { -- if (CompressedOops::shift() != 0 || d != s) { -- slli(d, s, CompressedOops::shift()); -+ if (Universe::narrow_oop_base() == NULL) { -+ if (Universe::narrow_oop_shift() != 0 || d != s) { -+ slli(d, s, Universe::narrow_oop_shift()); - } - } else { - Label done; -@@ -3004,7 +3004,7 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - InstructionMark im(this); - RelocationHolder rspec = metadata_Relocation::spec(index); - code_section()->relocate(inst_mark(), rspec); -- narrowKlass nk = CompressedKlassPointers::encode(k); -+ narrowKlass nk = Klass::encode_klass(k); - li32(dst, nk); - zero_extend(dst, dst, 32); - } -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 2ef28771e2e..953bca3cbd8 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -29,7 +29,6 @@ - - #include "asm/assembler.hpp" - #include "metaprogramming/enableIf.hpp" --#include "oops/compressedOops.hpp" - - // MacroAssembler extends Assembler by frequently used macros. - // -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 2e7eed8fb52..24214964243 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1407,7 +1407,7 @@ void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const - st->print_cr("# MachUEPNode"); - if (UseCompressedClassPointers) { - st->print_cr("\tlwu t0, [j_rarg0, oopDesc::klass_offset_in_bytes()]\t# compressed klass"); -- if (CompressedKlassPointers::shift() != 0) { -+ if (Universe::narrow_klass_shift() != 0) { - st->print_cr("\tdecode_klass_not_null t0, t0"); - } - } else { -@@ -3255,7 +3255,7 @@ operand indOffL(iRegP reg, immLOffset off) - - operand indirectN(iRegN reg) - %{ -- predicate(CompressedOops::shift() == 0); -+ predicate(Universe::narrow_oop_shift() == 0); - constraint(ALLOC_IN_RC(ptr_reg)); - match(DecodeN reg); - op_cost(0); -@@ -3270,7 +3270,7 @@ operand indirectN(iRegN reg) - - operand indOffIN(iRegN reg, immIOffset off) - %{ -- predicate(CompressedOops::shift() == 0); -+ predicate(Universe::narrow_oop_shift() == 0); - constraint(ALLOC_IN_RC(ptr_reg)); - match(AddP (DecodeN reg) off); - op_cost(0); -@@ -3285,7 +3285,7 @@ operand indOffIN(iRegN reg, immIOffset off) - - operand indOffLN(iRegN reg, immLOffset off) - %{ -- predicate(CompressedOops::shift() == 0); -+ predicate(Universe::narrow_oop_shift() == 0); - constraint(ALLOC_IN_RC(ptr_reg)); - match(AddP (DecodeN reg) off); - op_cost(0); -@@ -7947,7 +7947,7 @@ instruct convP2I(iRegINoSp dst, iRegP src) %{ - // in case of 32bit oops (heap < 4Gb). - instruct convN2I(iRegINoSp dst, iRegN src) - %{ -- predicate(CompressedOops::shift() == 0); -+ predicate(Universe::narrow_oop_shift() == 0); - match(Set dst (ConvL2I (CastP2X (DecodeN src)))); - - ins_cost(ALU_COST); - -From 81d8ea9077484f1dd20033390cbd3c1844b1b966 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 17:11:20 +0800 -Subject: [PATCH 099/140] Revert JDK-8247912: Make narrowOop a scoped enum - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index becc1656358..e2841c28c37 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1305,7 +1305,7 @@ int MacroAssembler::patch_oop(address insn_addr, address o) { - // instruction. - if (NativeInstruction::is_li32_at(insn_addr)) { - // Move narrow OOP -- uint32_t n = CompressedOops::narrow_oop_value(cast_to_oop(o)); -+ narrowOop n = CompressedOops::encode((oop)o); - return patch_imm_in_li32(insn_addr, (int32_t)n); - } else if (NativeInstruction::is_movptr_at(insn_addr)) { - // Move wide OOP - -From f980e03cb17804ff72958dd13505058048c04da8 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 17:20:05 +0800 -Subject: [PATCH 100/140] Revert JDK-8260467: Move well-known classes from - systemDictionary.hpp to vmClasses.hpp - ---- - src/hotspot/cpu/riscv/methodHandles_riscv.cpp | 11 +++++------ - src/hotspot/cpu/riscv/methodHandles_riscv.hpp | 4 ++-- - 2 files changed, 7 insertions(+), 8 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -index e070b8096a6..fd907f77afb 100644 ---- a/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -27,7 +27,6 @@ - #include "precompiled.hpp" - #include "asm/macroAssembler.hpp" - #include "classfile/javaClasses.inline.hpp" --#include "classfile/vmClasses.hpp" - #include "interpreter/interpreter.hpp" - #include "interpreter/interpreterRuntime.hpp" - #include "memory/allocation.inline.hpp" -@@ -50,7 +49,7 @@ - void MethodHandles::load_klass_from_Class(MacroAssembler* _masm, Register klass_reg) { - assert_cond(_masm != NULL); - if (VerifyMethodHandles) { -- verify_klass(_masm, klass_reg, VM_CLASS_ID(java_lang_Class), -+ verify_klass(_masm, klass_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_Class), - "MH argument is a Class"); - } - __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset_in_bytes())); -@@ -68,11 +67,11 @@ static int check_nonzero(const char* xname, int x) { - - #ifdef ASSERT - void MethodHandles::verify_klass(MacroAssembler* _masm, -- Register obj, vmClassID klass_id, -+ Register obj, SystemDictionary::WKID klass_id, - const char* error_message) { - assert_cond(_masm != NULL); -- InstanceKlass** klass_addr = vmClasses::klass_addr_at(klass_id); -- Klass* klass = vmClasses::klass_at(klass_id); -+ InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); -+ Klass* klass = SystemDictionary::well_known_klass(klass_id); - Register temp = t1; - Register temp2 = t0; // used by MacroAssembler::cmpptr - Label L_ok, L_bad; -@@ -280,7 +279,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, - // The method is a member invoker used by direct method handles. - if (VerifyMethodHandles) { - // make sure the trailing argument really is a MemberName (caller responsibility) -- verify_klass(_masm, member_reg, VM_CLASS_ID(java_lang_invoke_MemberName), -+ verify_klass(_masm, member_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_invoke_MemberName), - "MemberName required for invokeVirtual etc."); - } - -diff --git a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp -index f73aba29d67..65493eba764 100644 ---- a/src/hotspot/cpu/riscv/methodHandles_riscv.hpp -+++ b/src/hotspot/cpu/riscv/methodHandles_riscv.hpp -@@ -36,11 +36,11 @@ enum /* platform_dependent_constants */ { - static void load_klass_from_Class(MacroAssembler* _masm, Register klass_reg); - - static void verify_klass(MacroAssembler* _masm, -- Register obj, vmClassID klass_id, -+ Register obj, SystemDictionary::WKID klass_id, - const char* error_message = "wrong klass") NOT_DEBUG_RETURN; - - static void verify_method_handle(MacroAssembler* _masm, Register mh_reg) { -- verify_klass(_masm, mh_reg, VM_CLASS_ID(java_lang_invoke_MethodHandle), -+ verify_klass(_masm, mh_reg, SystemDictionary::WK_KLASS_ENUM_NAME(java_lang_invoke_MethodHandle), - "reference is a MH"); - } - - -From 2c68b064100b5abaca80926e213280ea82ff161a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 17:32:15 +0800 -Subject: [PATCH 101/140] Revert JDK-8268858: Determine register pressure - automatically by the number of available registers for allocation - ---- - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 2 ++ - src/hotspot/cpu/riscv/riscv.ad | 27 ---------------------- - 2 files changed, 2 insertions(+), 27 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -index 6c301cdae04..33d78fb2f6f 100644 ---- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -@@ -44,8 +44,10 @@ define_pd_global(intx, CompileThreshold, 10000); - - define_pd_global(intx, OnStackReplacePercentage, 140); - define_pd_global(intx, ConditionalMoveLimit, 0); -+define_pd_global(intx, FLOATPRESSURE, 32); - define_pd_global(intx, FreqInlineSize, 325); - define_pd_global(intx, MinJumpTableSize, 10); -+define_pd_global(intx, INTPRESSURE, 24); - define_pd_global(intx, InteriorEntryAlignment, 16); - define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); - define_pd_global(intx, LoopUnrollLimit, 60); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 24214964243..c5e0ae23029 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1719,33 +1719,6 @@ bool Matcher::is_spillable_arg(int reg) - return can_be_java_arg(reg); - } - --uint Matcher::int_pressure_limit() --{ -- // A derived pointer is live at CallNode and then is flagged by RA -- // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip -- // derived pointers and lastly fail to spill after reaching maximum -- // number of iterations. Lowering the default pressure threshold to -- // (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become -- // a high register pressure area of the code so that split_DEF can -- // generate DefinitionSpillCopy for the derived pointer. -- uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1; -- if (!PreserveFramePointer) { -- // When PreserveFramePointer is off, frame pointer is allocatable, -- // but different from other SOC registers, it is excluded from -- // fatproj's mask because its save type is No-Save. Decrease 1 to -- // ensure high pressure at fatproj when PreserveFramePointer is off. -- // See check_pressure_at_fatproj(). -- default_int_pressure_threshold--; -- } -- return (INTPRESSURE == -1) ? default_int_pressure_threshold : INTPRESSURE; --} -- --uint Matcher::float_pressure_limit() --{ -- // _FLOAT_REG_mask is generated by adlc from the float_reg register class. -- return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE; --} -- - bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { - return false; - } - -From 932ebd6238ea7703dc3164e4506af332f6847592 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 17:51:12 +0800 -Subject: [PATCH 102/140] Revert JDK-8276563: Undefined Behaviour in class - Assembler && 8257882: Implement linkToNative intrinsic on AArch64 (the - register part) - ---- - .../cpu/riscv/globalDefinitions_riscv.hpp | 2 - - src/hotspot/cpu/riscv/register_riscv.cpp | 4 - - src/hotspot/cpu/riscv/register_riscv.hpp | 123 +++++++++++++----- - 3 files changed, 91 insertions(+), 38 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -index 2936837d951..ffd420da024 100644 ---- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -@@ -47,6 +47,4 @@ const bool CCallingConventionRequiresIntsAsLongs = false; - - #define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false - --#define USE_POINTERS_TO_REGISTER_IMPL_ARRAY -- - #endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP -diff --git a/src/hotspot/cpu/riscv/register_riscv.cpp b/src/hotspot/cpu/riscv/register_riscv.cpp -index 96cf1996a83..ef60cb3bb05 100644 ---- a/src/hotspot/cpu/riscv/register_riscv.cpp -+++ b/src/hotspot/cpu/riscv/register_riscv.cpp -@@ -26,10 +26,6 @@ - #include "precompiled.hpp" - #include "register_riscv.hpp" - --REGISTER_IMPL_DEFINITION(Register, RegisterImpl, RegisterImpl::number_of_registers); --REGISTER_IMPL_DEFINITION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); --REGISTER_IMPL_DEFINITION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); -- - const int ConcreteRegisterImpl::max_gpr = RegisterImpl::number_of_registers * - RegisterImpl::max_slots_per_register; - -diff --git a/src/hotspot/cpu/riscv/register_riscv.hpp b/src/hotspot/cpu/riscv/register_riscv.hpp -index d697751f55f..f64a06eb89f 100644 ---- a/src/hotspot/cpu/riscv/register_riscv.hpp -+++ b/src/hotspot/cpu/riscv/register_riscv.hpp -@@ -47,13 +47,13 @@ typedef VMRegImpl* VMReg; - - // Use Register as shortcut - class RegisterImpl; --typedef const RegisterImpl* Register; -+typedef RegisterImpl* Register; - --inline constexpr Register as_Register(int encoding); -+inline Register as_Register(int encoding) { -+ return (Register)(intptr_t) encoding; -+} - - class RegisterImpl: public AbstractRegisterImpl { -- static constexpr Register first(); -- - public: - enum { - number_of_registers = 32, -@@ -66,16 +66,16 @@ class RegisterImpl: public AbstractRegisterImpl { - }; - - // derived registers, offsets, and addresses -- const Register successor() const { return this + 1; } -+ const Register successor() const { return as_Register(encoding() + 1); } - - // construction -- inline friend constexpr Register as_Register(int encoding); -+ inline friend Register as_Register(int encoding); - - VMReg as_VMReg() const; - - // accessors - int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -- int encoding_nocheck() const { return this - first(); } -+ int encoding_nocheck() const { return (intptr_t)this; } - bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } - const char* name() const; - -@@ -93,9 +93,11 @@ class RegisterImpl: public AbstractRegisterImpl { - return encoding_nocheck() >= compressed_register_base && - encoding_nocheck() <= compressed_register_top; - } --}; - --REGISTER_IMPL_DECLARATION(Register, RegisterImpl, RegisterImpl::number_of_registers); -+ // Return the bit which represents this register. This is intended -+ // to be ORed into a bitmask: for usage see class RegSet below. -+ uint64_t bit(bool should_set = true) const { return should_set ? 1 << encoding() : 0; } -+}; - - // The integer registers of the RISCV architecture - -@@ -136,14 +138,14 @@ CONSTANT_REGISTER_DECLARATION(Register, x31, (31)); - - // Use FloatRegister as shortcut - class FloatRegisterImpl; --typedef const FloatRegisterImpl* FloatRegister; -+typedef FloatRegisterImpl* FloatRegister; - --inline constexpr FloatRegister as_FloatRegister(int encoding); -+inline FloatRegister as_FloatRegister(int encoding) { -+ return (FloatRegister)(intptr_t) encoding; -+} - - // The implementation of floating point registers for the architecture - class FloatRegisterImpl: public AbstractRegisterImpl { -- static constexpr FloatRegister first(); -- - public: - enum { - number_of_registers = 32, -@@ -155,18 +157,16 @@ class FloatRegisterImpl: public AbstractRegisterImpl { - }; - - // construction -- inline friend constexpr FloatRegister as_FloatRegister(int encoding); -+ inline friend FloatRegister as_FloatRegister(int encoding); - - VMReg as_VMReg() const; - - // derived registers, offsets, and addresses -- FloatRegister successor() const { -- return as_FloatRegister((encoding() + 1) % (unsigned)number_of_registers); -- } -+ FloatRegister successor() const { return as_FloatRegister(encoding() + 1); } - - // accessors - int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -- int encoding_nocheck() const { return this - first(); } -+ int encoding_nocheck() const { return (intptr_t)this; } - int is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } - const char* name() const; - -@@ -186,8 +186,6 @@ class FloatRegisterImpl: public AbstractRegisterImpl { - } - }; - --REGISTER_IMPL_DECLARATION(FloatRegister, FloatRegisterImpl, FloatRegisterImpl::number_of_registers); -- - // The float registers of the RISCV architecture - - CONSTANT_REGISTER_DECLARATION(FloatRegister, fnoreg , (-1)); -@@ -227,14 +225,14 @@ CONSTANT_REGISTER_DECLARATION(FloatRegister, f31 , (31)); - - // Use VectorRegister as shortcut - class VectorRegisterImpl; --typedef const VectorRegisterImpl* VectorRegister; -+typedef VectorRegisterImpl* VectorRegister; - --inline constexpr VectorRegister as_VectorRegister(int encoding); -+inline VectorRegister as_VectorRegister(int encoding) { -+ return (VectorRegister)(intptr_t) encoding; -+} - - // The implementation of vector registers for RVV - class VectorRegisterImpl: public AbstractRegisterImpl { -- static constexpr VectorRegister first(); -- - public: - enum { - number_of_registers = 32, -@@ -242,23 +240,21 @@ class VectorRegisterImpl: public AbstractRegisterImpl { - }; - - // construction -- inline friend constexpr VectorRegister as_VectorRegister(int encoding); -+ inline friend VectorRegister as_VectorRegister(int encoding); - - VMReg as_VMReg() const; - - // derived registers, offsets, and addresses -- VectorRegister successor() const { return this + 1; } -+ VectorRegister successor() const { return as_VectorRegister(encoding() + 1); } - - // accessors - int encoding() const { assert(is_valid(), "invalid register"); return encoding_nocheck(); } -- int encoding_nocheck() const { return this - first(); } -+ int encoding_nocheck() const { return (intptr_t)this; } - bool is_valid() const { return (unsigned)encoding_nocheck() < number_of_registers; } - const char* name() const; - - }; - --REGISTER_IMPL_DECLARATION(VectorRegister, VectorRegisterImpl, VectorRegisterImpl::number_of_registers); -- - // The vector registers of RVV - CONSTANT_REGISTER_DECLARATION(VectorRegister, vnoreg , (-1)); - -@@ -315,8 +311,71 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { - static const int max_fpr; - }; - --typedef AbstractRegSet RegSet; --typedef AbstractRegSet FloatRegSet; --typedef AbstractRegSet VectorRegSet; -+// A set of registers -+class RegSet { -+ uint32_t _bitset; -+ -+ RegSet(uint32_t bitset) : _bitset(bitset) { } -+ -+public: -+ -+ RegSet() : _bitset(0) { } -+ -+ RegSet(Register r1) : _bitset(r1->bit()) { } -+ -+ RegSet operator+(const RegSet aSet) const { -+ RegSet result(_bitset | aSet._bitset); -+ return result; -+ } -+ -+ RegSet operator-(const RegSet aSet) const { -+ RegSet result(_bitset & ~aSet._bitset); -+ return result; -+ } -+ -+ RegSet &operator+=(const RegSet aSet) { -+ *this = *this + aSet; -+ return *this; -+ } -+ -+ RegSet &operator-=(const RegSet aSet) { -+ *this = *this - aSet; -+ return *this; -+ } -+ -+ static RegSet of(Register r1) { -+ return RegSet(r1); -+ } -+ -+ static RegSet of(Register r1, Register r2) { -+ return of(r1) + r2; -+ } -+ -+ static RegSet of(Register r1, Register r2, Register r3) { -+ return of(r1, r2) + r3; -+ } -+ -+ static RegSet of(Register r1, Register r2, Register r3, Register r4) { -+ return of(r1, r2, r3) + r4; -+ } -+ -+ static RegSet range(Register start, Register end) { -+ uint32_t bits = ~0; -+ bits <<= start->encoding(); -+ bits <<= 31 - end->encoding(); -+ bits >>= 31 - end->encoding(); -+ -+ return RegSet(bits); -+ } -+ -+ uint32_t bits() const { return _bitset; } -+ -+private: -+ -+ Register first() { -+ uint32_t first = _bitset & -_bitset; -+ return first ? as_Register(exact_log2(first)) : noreg; -+ } -+}; - - #endif // CPU_RISCV_REGISTER_RISCV_HPP - -From 9c85aa8d3387d795f9c2f4795ffc7f9d7f814d92 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 19:24:49 +0800 -Subject: [PATCH 103/140] Revert JDK-8240363: Refactor Compile::Output() to its - own Phase - ---- - .../cpu/riscv/macroAssembler_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/riscv.ad | 20 +++++++++---------- - 2 files changed, 11 insertions(+), 11 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index e2841c28c37..656334f326b 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -3027,7 +3027,7 @@ address MacroAssembler::trampoline_call(Address entry, CodeBuffer* cbuf) { - CompileTask* task = ciEnv::current()->task(); - in_scratch_emit_size = - (task != NULL && is_c2_compile(task->comp_level()) && -- Compile::current()->output()->in_scratch_emit_size()); -+ Compile::current()->in_scratch_emit_size()); - #endif - if (!in_scratch_emit_size) { - address stub = emit_trampoline_stub(offset(), entry.target()); -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c5e0ae23029..d736750d02d 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1029,7 +1029,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { - //============================================================================= - const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; - --int ConstantTable::calculate_table_base_offset() const { -+int Compile::ConstantTable::calculate_table_base_offset() const { - return 0; // absolute addressing, no offset - } - -@@ -1058,9 +1058,9 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - assert_cond(st != NULL && ra_ != NULL); - Compile* C = ra_->C; - -- int framesize = C->output()->frame_slots() << LogBytesPerInt; -+ int framesize = C->frame_slots() << LogBytesPerInt; - -- if (C->output()->need_stack_bang(framesize)) { -+ if (C->need_stack_bang(framesize)) { - st->print("# stack bang size=%d\n\t", framesize); - } - -@@ -1077,7 +1077,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - MacroAssembler _masm(&cbuf); - - // n.b. frame size includes space for return pc and fp -- const int framesize = C->output()->frame_size_in_bytes(); -+ const int framesize = C->frame_size_in_bytes(); - - // insert a nop at the start of the prolog so we can patch in a - // branch if we need to invalidate the method later -@@ -1085,8 +1085,8 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - - assert_cond(C != NULL); - -- int bangsize = C->output()->bang_size_in_bytes(); -- if (C->output()->need_stack_bang(bangsize)) { -+ int bangsize = C->bang_size_in_bytes(); -+ if (C->need_stack_bang(bangsize)) { - __ generate_stack_overflow_check(bangsize); - } - -@@ -1096,12 +1096,12 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - Unimplemented(); - } - -- C->output()->set_frame_complete(cbuf.insts_size()); -+ C->set_frame_complete(cbuf.insts_size()); - - if (C->has_mach_constant_base_node()) { - // NOTE: We set the table base offset here because users might be - // emitted before MachConstantBaseNode. -- ConstantTable& constant_table = C->output()->constant_table(); -+ Compile::ConstantTable& constant_table = C->constant_table(); - constant_table.set_table_base_offset(constant_table.calculate_table_base_offset()); - } - } -@@ -1125,7 +1125,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const { - assert_cond(st != NULL && ra_ != NULL); - Compile* C = ra_->C; - assert_cond(C != NULL); -- int framesize = C->output()->frame_size_in_bytes(); -+ int framesize = C->frame_size_in_bytes(); - - st->print("# pop frame %d\n\t", framesize); - -@@ -1152,7 +1152,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { - Compile* C = ra_->C; - MacroAssembler _masm(&cbuf); - assert_cond(C != NULL); -- int framesize = C->output()->frame_size_in_bytes(); -+ int framesize = C->frame_size_in_bytes(); - - __ remove_frame(framesize); - - -From 3a58114310a56ebca04ba44b4883d205096eb844 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 19:36:09 +0800 -Subject: [PATCH 104/140] Revert RotateLeft && RotateRight matching rules - ---- - src/hotspot/cpu/riscv/riscv.ad | 2 - - src/hotspot/cpu/riscv/riscv_b.ad | 76 -------------------------------- - 2 files changed, 78 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index d736750d02d..1e6495692da 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1505,8 +1505,6 @@ const bool Matcher::match_rule_supported(int opcode) { - case Op_PopCountL: - return UsePopCountInstruction; - -- case Op_RotateRight: -- case Op_RotateLeft: - case Op_CountLeadingZerosI: - case Op_CountLeadingZerosL: - case Op_CountTrailingZerosI: -diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad -index 4488c1c4031..b9e04c432e1 100644 ---- a/src/hotspot/cpu/riscv/riscv_b.ad -+++ b/src/hotspot/cpu/riscv/riscv_b.ad -@@ -25,82 +25,6 @@ - - // RISCV Bit-Manipulation Extension Architecture Description File - --instruct rorI_imm_rvb(iRegINoSp dst, iRegI src, immI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateRight src shift)); -- -- format %{ "roriw $dst, $src, ($shift & 0x1f)\t#@rorI_imm_rvb" %} -- -- ins_cost(ALU_COST); -- ins_encode %{ -- __ roriw(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x1f); -- %} -- -- ins_pipe(ialu_reg_shift); --%} -- --instruct rorL_imm_rvb(iRegLNoSp dst, iRegL src, immI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateRight src shift)); -- -- format %{ "rori $dst, $src, ($shift & 0x3f)\t#@rorL_imm_rvb" %} -- -- ins_cost(ALU_COST); -- ins_encode %{ -- __ rori(as_Register($dst$$reg), as_Register($src$$reg), $shift$$constant & 0x3f); -- %} -- -- ins_pipe(ialu_reg_shift); --%} -- --instruct rorI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateRight src shift)); -- -- format %{ "rorw $dst, $src, $shift\t#@rorI_reg_rvb" %} -- ins_cost(ALU_COST); -- ins_encode %{ -- __ rorw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -- %} -- ins_pipe(ialu_reg_reg); --%} -- --instruct rorL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateRight src shift)); -- -- format %{ "ror $dst, $src, $shift\t#@rorL_reg_rvb" %} -- ins_cost(ALU_COST); -- ins_encode %{ -- __ ror(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -- %} -- ins_pipe(ialu_reg_reg); --%} -- --instruct rolI_reg_rvb(iRegINoSp dst, iRegI src, iRegI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateLeft src shift)); -- -- format %{ "rolw $dst, $src, $shift\t#@rolI_reg_rvb" %} -- ins_cost(ALU_COST); -- ins_encode %{ -- __ rolw(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -- %} -- ins_pipe(ialu_reg_reg); --%} -- --instruct rolL_reg_rvb(iRegLNoSp dst, iRegL src, iRegI shift) %{ -- predicate(UseRVB); -- match(Set dst (RotateLeft src shift)); -- -- format %{ "rol $dst, $src, $shift\t#@rolL_reg_rvb" %} -- ins_cost(ALU_COST); -- ins_encode %{ -- __ rol(as_Register($dst$$reg), as_Register($src$$reg), as_Register($shift$$reg)); -- %} -- ins_pipe(ialu_reg_reg); --%} -- - // Convert oop into int for vectors alignment masking - instruct convP2I_rvb(iRegINoSp dst, iRegP src) %{ - predicate(UseRVB); - -From 21577388eda0218eeb4b28bc71ecf5737d40639e Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 19:49:28 +0800 -Subject: [PATCH 105/140] Revert JDK-8230565: ZGC: Redesign C2 load barrier to - expand on the MachNode level - ---- - src/hotspot/cpu/riscv/riscv.ad | 14 ++++---------- - 1 file changed, 4 insertions(+), 10 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 1e6495692da..533eaf843e3 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -4324,7 +4324,6 @@ instruct loadRange(iRegINoSp dst, memory mem) - instruct loadP(iRegPNoSp dst, memory mem) - %{ - match(Set dst (LoadP mem)); -- predicate(n->as_Load()->barrier_data() == 0); - - ins_cost(LOAD_COST); - format %{ "ld $dst, $mem\t# ptr, #@loadP" %} -@@ -5060,8 +5059,6 @@ instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegLNoS - - instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(n->as_LoadStore()->barrier_data() == 0); -- - match(Set res (CompareAndSwapP mem (Binary oldval newval))); - - ins_cost(LOAD_COST + STORE_COST + ALU_COST * 6 + BRANCH_COST * 4); -@@ -5181,7 +5178,7 @@ instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegLNoSp oldval, iRegL - - instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); -+ predicate(needs_acquiring_load_reserved(n)); - - match(Set res (CompareAndSwapP mem (Binary oldval newval))); - -@@ -5327,7 +5324,6 @@ instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN ne - - instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(n->as_LoadStore()->barrier_data() == 0); - match(Set res (CompareAndExchangeP mem (Binary oldval newval))); - - ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 3 + ALU_COST); -@@ -5462,7 +5458,7 @@ instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN - - instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); -+ predicate(needs_acquiring_load_reserved(n)); - - match(Set res (CompareAndExchangeP mem (Binary oldval newval))); - -@@ -5592,7 +5588,6 @@ instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN ne - - instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(n->as_LoadStore()->barrier_data() == 0); - match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); - - ins_cost(LOAD_COST + STORE_COST + BRANCH_COST * 2 + ALU_COST * 2); -@@ -5731,7 +5726,7 @@ instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN - - instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval) - %{ -- predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); -+ predicate(needs_acquiring_load_reserved(n)); - - match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); - -@@ -5798,7 +5793,6 @@ instruct get_and_setN(indirect mem, iRegN newv, iRegINoSp prev) - - instruct get_and_setP(indirect mem, iRegP newv, iRegPNoSp prev) - %{ -- predicate(n->as_LoadStore()->barrier_data() == 0); - match(Set prev (GetAndSetP mem newv)); - - ins_cost(ALU_COST); -@@ -5865,7 +5859,7 @@ instruct get_and_setNAcq(indirect mem, iRegN newv, iRegINoSp prev) - - instruct get_and_setPAcq(indirect mem, iRegP newv, iRegPNoSp prev) - %{ -- predicate(needs_acquiring_load_reserved(n) && (n->as_LoadStore()->barrier_data() == 0)); -+ predicate(needs_acquiring_load_reserved(n)); - - match(Set prev (GetAndSetP mem newv)); - - -From 4673921af60f4779d4322256f92bb60a850cb035 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 19:51:09 +0800 -Subject: [PATCH 106/140] Revert JDK-8252990: Intrinsify Unsafe.storeStoreFence - ---- - src/hotspot/cpu/riscv/riscv.ad | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 533eaf843e3..5fa3b85c001 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -7537,7 +7537,6 @@ instruct membar_release() %{ - - instruct membar_storestore() %{ - match(MemBarStoreStore); -- match(StoreStoreFence); - ins_cost(ALU_COST); - - format %{ "MEMBAR-store-store\t#@membar_storestore" %} - -From e254a03e87ffc6d8f563dbd7db1b607a95657263 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 19:54:02 +0800 -Subject: [PATCH 107/140] Revert JDK-8255150: Add utility methods to check long - indexes and ranges && JDK-8252372: Check if cloning is required to move loads - out of loops in PhaseIdealLoop::split_if_with_blocks_post() - ---- - src/hotspot/cpu/riscv/riscv.ad | 33 --------------------------------- - 1 file changed, 33 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 5fa3b85c001..388e65f623d 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -7621,17 +7621,6 @@ instruct castPP(iRegPNoSp dst) - ins_pipe(pipe_class_empty); - %} - --instruct castLL(iRegL dst) --%{ -- match(Set dst (CastLL dst)); -- -- size(0); -- format %{ "# castLL of $dst, #@castLL" %} -- ins_encode(/* empty encoding */); -- ins_cost(0); -- ins_pipe(pipe_class_empty); --%} -- - instruct castII(iRegI dst) - %{ - match(Set dst (CastII dst)); -@@ -7654,28 +7643,6 @@ instruct checkCastPP(iRegPNoSp dst) - ins_pipe(pipe_class_empty); - %} - --instruct castFF(fRegF dst) --%{ -- match(Set dst (CastFF dst)); -- -- size(0); -- format %{ "# castFF of $dst" %} -- ins_encode(/* empty encoding */); -- ins_cost(0); -- ins_pipe(pipe_class_empty); --%} -- --instruct castDD(fRegD dst) --%{ -- match(Set dst (CastDD dst)); -- -- size(0); -- format %{ "# castDD of $dst" %} -- ins_encode(/* empty encoding */); -- ins_cost(0); -- ins_pipe(pipe_class_empty); --%} -- - // ============================================================================ - // Convert Instructions - - -From 2c1820363992d09ef0cd2ed2553c04e0f7afd91f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 20:02:14 +0800 -Subject: [PATCH 108/140] Revert reset_label part of JDK-8248411: [aarch64] - Insufficient error handling when CodeBuffer is exhausted - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 2 +- - src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 14 +++++--------- - 2 files changed, 6 insertions(+), 10 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 656334f326b..37ccf132986 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -3784,7 +3784,7 @@ address MacroAssembler::zero_words(Register ptr, Register cnt) - if (StubRoutines::riscv::complete()) { - address tpc = trampoline_call(zero_blocks); - if (tpc == NULL) { -- DEBUG_ONLY(reset_labels(around)); -+ DEBUG_ONLY(reset_labels1(around)); - postcond(pc() == badAddress); - return NULL; - } -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 953bca3cbd8..45ffc663963 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -815,17 +815,13 @@ class MacroAssembler: public Assembler { - private: - - #ifdef ASSERT -- // Template short-hand support to clean-up after a failed call to trampoline -+ // Macro short-hand support to clean-up after a failed call to trampoline - // call generation (see trampoline_call() below), when a set of Labels must - // be reset (before returning). -- template -- void reset_labels(Label& lbl, More&... more) { -- lbl.reset(); reset_labels(more...); -- } -- template -- void reset_labels(Label& lbl) { -- lbl.reset(); -- } -+#define reset_labels1(L1) L1.reset() -+#define reset_labels2(L1, L2) L1.reset(); L2.reset() -+#define reset_labels3(L1, L2, L3) L1.reset(); reset_labels2(L2, L3) -+#define reset_labels5(L1, L2, L3, L4, L5) reset_labels2(L1, L2); reset_labels3(L3, L4, L5) - #endif - void repne_scan(Register addr, Register value, Register count, Register tmp); - - -From 014972a0778b8c5568fae9e92d286b634cb44674 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 20:30:49 +0800 -Subject: [PATCH 109/140] Revert JDK-8242289: C2: Support platform-specific - node cloning in Matcher - ---- - src/hotspot/cpu/riscv/riscv.ad | 12 +----------- - 1 file changed, 1 insertion(+), 11 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 388e65f623d..7cd6c2995ba 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1765,20 +1765,10 @@ bool size_fits_all_mem_uses(AddPNode* addp, int shift) { - - const bool Matcher::convi2l_type_required = false; - --// Should the Matcher clone input 'm' of node 'n'? --bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { -- assert_cond(m != NULL); -- if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con) -- mstack.push(m, Visit); // m = ShiftCntV -- return true; -- } -- return false; --} -- - // Should the Matcher clone shifts on addressing modes, expecting them - // to be subsumed into complex addressing expressions or compute them - // into registers? --bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { -+bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) { - return clone_base_plus_offset_address(m, mstack, address_visited); - } - - -From d15e155e9b84f4789cfbb1cf75382be859b0a8ca Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 20:40:00 +0800 -Subject: [PATCH 110/140] Revert JDK-8255782: Turn UseTLAB and ResizeTLAB from - product_pd to product, defaulting to "true" - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 2 ++ - src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index 8f2f4e0e81d..25e00bea901 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -34,6 +34,8 @@ - - #ifndef TIERED - define_pd_global(bool, BackgroundCompilation, true ); -+define_pd_global(bool, UseTLAB, true ); -+define_pd_global(bool, ResizeTLAB, true ); - define_pd_global(bool, InlineIntrinsics, true ); - define_pd_global(bool, PreferInterpreterNativeStubs, false); - define_pd_global(bool, ProfileTraps, false); -diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -index 33d78fb2f6f..3da1f1c6d86 100644 ---- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp -@@ -33,6 +33,8 @@ - // (see c2_globals.hpp). Alpha-sorted. - - define_pd_global(bool, BackgroundCompilation, true); -+define_pd_global(bool, UseTLAB, true); -+define_pd_global(bool, ResizeTLAB, true); - define_pd_global(bool, CICompileOSR, true); - define_pd_global(bool, InlineIntrinsics, true); - define_pd_global(bool, PreferInterpreterNativeStubs, false); - -From f3fa0cfa987743b4ee83332ddf71add421561908 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 20:49:57 +0800 -Subject: [PATCH 111/140] Revert JDK-8265245: depChecker_ don't have any - functionalities - ---- - src/hotspot/cpu/riscv/depChecker_riscv.hpp | 32 ++++++++++++++++++++++ - 1 file changed, 32 insertions(+) - create mode 100644 src/hotspot/cpu/riscv/depChecker_riscv.hpp - -diff --git a/src/hotspot/cpu/riscv/depChecker_riscv.hpp b/src/hotspot/cpu/riscv/depChecker_riscv.hpp -new file mode 100644 -index 00000000000..e9ff307b647 ---- /dev/null -+++ b/src/hotspot/cpu/riscv/depChecker_riscv.hpp -@@ -0,0 +1,32 @@ -+/* -+ * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2014, Red Hat Inc. All rights reserved. -+ * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ * -+ */ -+ -+#ifndef CPU_RISCV_VM_DEPCHECKER_RISCV_HPP -+#define CPU_RISCV_VM_DEPCHECKER_RISCV_HPP -+ -+// Nothing to do on riscv -+ -+#endif // CPU_RISCV_VM_DEPCHECKER_RISCV_HPP - -From 97a3d4d3b98a450aa316eaa94103cf8473d12d50 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 20:58:34 +0800 -Subject: [PATCH 112/140] Revert JDK-8241438: Move IntelJccErratum mitigation - code to platform-specific code - ---- - src/hotspot/cpu/riscv/riscv.ad | 18 ------------------ - 1 file changed, 18 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index 7cd6c2995ba..fc6823daf8b 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -740,13 +740,6 @@ class HandlerImpl { - } - }; - --class Node::PD { --public: -- enum NodeFlags { -- _last_flag = Node::_last_flag -- }; --}; -- - bool is_CAS(int opcode, bool maybe_volatile); - - // predicate controlling translation of CompareAndSwapX -@@ -805,17 +798,6 @@ void reg_mask_init() { - } - } - --void PhaseOutput::pd_perform_mach_node_analysis() { --} -- --int MachNode::pd_alignment_required() const { -- return 1; --} -- --int MachNode::compute_padding(int current_offset) const { -- return 0; --} -- - // is_CAS(int opcode, bool maybe_volatile) - // - // return true if opcode is one of the possible CompareAndSwapX - -From 8a3e7b81b79918a4f2feb4d9226ab8be6c43c28a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:03:47 +0800 -Subject: [PATCH 113/140] Revert JDK-8260355: AArch64: deoptimization stub - should save vector registers - ---- - src/hotspot/cpu/riscv/registerMap_riscv.cpp | 45 --------------------- - src/hotspot/cpu/riscv/registerMap_riscv.hpp | 1 - - 2 files changed, 46 deletions(-) - delete mode 100644 src/hotspot/cpu/riscv/registerMap_riscv.cpp - -diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.cpp b/src/hotspot/cpu/riscv/registerMap_riscv.cpp -deleted file mode 100644 -index 26c1edc36ff..00000000000 ---- a/src/hotspot/cpu/riscv/registerMap_riscv.cpp -+++ /dev/null -@@ -1,45 +0,0 @@ --/* -- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2021, Huawei Technologies Co., Ltd. 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 "runtime/registerMap.hpp" --#include "vmreg_riscv.inline.hpp" -- --address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { -- if (base_reg->is_VectorRegister()) { -- assert(base_reg->is_concrete(), "must pass base reg"); -- int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_fpr) / -- VectorRegisterImpl::max_slots_per_register; -- intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; -- address base_location = location(base_reg); -- if (base_location != NULL) { -- return base_location + offset_in_bytes; -- } else { -- return NULL; -- } -- } else { -- return location(base_reg->next(slot_idx)); -- } --} -diff --git a/src/hotspot/cpu/riscv/registerMap_riscv.hpp b/src/hotspot/cpu/riscv/registerMap_riscv.hpp -index f34349811a9..fef8ca9b64e 100644 ---- a/src/hotspot/cpu/riscv/registerMap_riscv.hpp -+++ b/src/hotspot/cpu/riscv/registerMap_riscv.hpp -@@ -33,7 +33,6 @@ - // This is the hook for finding a register in an "well-known" location, - // such as a register block of a predetermined format. - address pd_location(VMReg reg) const { return NULL; } -- address pd_location(VMReg base_reg, int slot_idx) const; - - // no PD state to clear or copy: - void pd_clear() {} - -From 5fc20f93a312f9189b55c5236c15a55b3da10cf9 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:05:37 +0800 -Subject: [PATCH 114/140] Revert JDK-8250914: Matcher::stack_direction() is - unused - ---- - src/hotspot/cpu/riscv/riscv.ad | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index fc6823daf8b..c21508b6e7c 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -2326,6 +2326,9 @@ encode %{ - // SP meets the minimum alignment. - - frame %{ -+ // What direction does stack grow in (assumed to be same for C & Java) -+ stack_direction(TOWARDS_LOW); -+ - // These three registers define part of the calling convention - // between compiled code and the interpreter. - - -From aab3322fd2507a3aeae39c69ba871400dd342834 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:15:45 +0800 -Subject: [PATCH 115/140] Revert CacheWB*Node matching rules - ---- - src/hotspot/cpu/riscv/riscv.ad | 8 -------- - 1 file changed, 8 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index c21508b6e7c..e410bd06aa6 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -1475,14 +1475,6 @@ const bool Matcher::match_rule_supported(int opcode) { - } - - switch (opcode) { -- case Op_CacheWB: // fall through -- case Op_CacheWBPreSync: // fall through -- case Op_CacheWBPostSync: -- if (!VM_Version::supports_data_cache_line_flush()) { -- return false; -- } -- break; -- - case Op_PopCountI: - case Op_PopCountL: - return UsePopCountInstruction; - -From 705981aaff19b442b55df8a038aab9c61133bc3a Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:21:10 +0800 -Subject: [PATCH 116/140] Revert JDK-8263595: Remove oop type punning in - JavaCallArguments - ---- - src/hotspot/cpu/riscv/jniTypes_riscv.hpp | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -index bc4e5758256..df3c0267eea 100644 ---- a/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -+++ b/src/hotspot/cpu/riscv/jniTypes_riscv.hpp -@@ -65,8 +65,9 @@ class JNITypes : private AllStatic { - } - - // Oops are stored in native format in one JavaCallArgument slot at *to. -- static inline void put_obj(const Handle& from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle.raw_value(); } -- static inline void put_obj(jobject from_handle, intptr_t *to, int& pos) { *(to + pos++) = (intptr_t)from_handle; } -+ static inline void put_obj(oop from, intptr_t *to) { *(oop *)(to + 0 ) = from; } -+ static inline void put_obj(oop from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = from; } -+ static inline void put_obj(oop *from, intptr_t *to, int& pos) { *(oop *)(to + pos++) = *from; } - - // Floats are stored in native format in one JavaCallArgument slot at *to. - static inline void put_float(jfloat from, intptr_t *to) { *(jfloat *)(to + 0 ) = from; } - -From bba22725b9f1386d8899941ccee3e8dc7f9a4a6f Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:33:01 +0800 -Subject: [PATCH 117/140] Revert JDK-8260012: Reduce inclusion of - collectedHeap.hpp and heapInspection.hpp - ---- - src/hotspot/cpu/riscv/frame_riscv.cpp | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp -index 40ec584b994..d4fcbdcbbde 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.cpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.cpp -@@ -598,7 +598,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) - oop* obj_p = (oop*)tos_addr; - obj = (obj_p == NULL) ? (oop)NULL : *obj_p; - } -- assert(Universe::is_in_heap_or_null(obj), "sanity check"); -+ assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); - *oop_result = obj; - break; - } - -From 49000a43408aba29d3dc9ee4e03219e6f85be602 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:35:21 +0800 -Subject: [PATCH 118/140] Revert JDK-8271869: AArch64: build errors with GCC11 - in frame::saved_oop_result - ---- - src/hotspot/cpu/riscv/frame_riscv.inline.hpp | 3 --- - 1 file changed, 3 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp -index 5ac1bf57f57..abd5bda7e49 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp -@@ -230,8 +230,6 @@ inline JavaCallWrapper** frame::entry_frame_call_wrapper_addr() const { - - - // Compiled frames --PRAGMA_DIAG_PUSH --PRAGMA_NONNULL_IGNORED - inline oop frame::saved_oop_result(RegisterMap* map) const { - oop* result_adr = (oop *)map->location(x10->as_VMReg()); - guarantee(result_adr != NULL, "bad register save location"); -@@ -243,6 +241,5 @@ inline void frame::set_saved_oop_result(RegisterMap* map, oop obj) { - guarantee(result_adr != NULL, "bad register save location"); - *result_adr = obj; - } --PRAGMA_DIAG_POP - - #endif // CPU_RISCV_FRAME_RISCV_INLINE_HPP - -From 14a46a85e65f6fec09ac566d49a6232216881adb Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:40:43 +0800 -Subject: [PATCH 119/140] Revert JDK-8230392: Define AArch64 as - MULTI_COPY_ATOMIC - ---- - src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -index ffd420da024..606f0fa0da3 100644 ---- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -@@ -33,10 +33,6 @@ const int StackAlignmentInBytes = 16; - // 32-bit integer argument values are extended to 64 bits. - const bool CCallingConventionRequiresIntsAsLongs = false; - --// RISCV has adopted a multicopy atomic model closely following --// that of ARMv8. --#define CPU_MULTI_COPY_ATOMIC -- - // To be safe, we deoptimize when we come across an access that needs - // patching. This is similar to what is done on aarch64. - #define DEOPTIMIZE_WHEN_PATCHING - -From 8740928267a831c62f1deb20c910e3c27716bc40 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:42:20 +0800 -Subject: [PATCH 120/140] Revert: JDK-8246689: Enable independent compressed - oops/class ptrs on Aarch64 JDK-8241825: Make compressed oops and compressed - class pointers independent (x86_64, PPC, S390) - ---- - src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -index 606f0fa0da3..acdf75d324e 100644 ---- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -@@ -41,6 +41,4 @@ const bool CCallingConventionRequiresIntsAsLongs = false; - - #define SUPPORT_RESERVED_STACK_AREA - --#define COMPRESSED_CLASS_POINTERS_DEPENDS_ON_COMPRESSED_OOPS false -- - #endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP - -From 94b40f4efccc19c8ac66eda6c57381a222b02d2d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:50:49 +0800 -Subject: [PATCH 121/140] Revert JDK-8222637: Obsolete NeedsDeoptSuspend - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index b78f258a764..a838a377829 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -32,6 +32,8 @@ - // Sets the default values for platform dependent flags used by the runtime system. - // (see globals.hpp) - -+define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this -+ - define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks - define_pd_global(bool, TrapBasedNullChecks, false); - define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs past to check cast - -From 09968c9fc102fd32bc628d3e6fd9d9adcbec4373 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 21:52:44 +0800 -Subject: [PATCH 122/140] Revert JDK-8220051: Remove global safepoint code - ---- - src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -index acdf75d324e..d6ce8da07b8 100644 ---- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp -@@ -41,4 +41,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; - - #define SUPPORT_RESERVED_STACK_AREA - -+#define THREAD_LOCAL_POLL -+ - #endif // CPU_RISCV_GLOBALDEFINITIONS_RISCV_HPP - -From 2f4fb2b5ac420d456421592dc09b81244636ba4d Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 22:00:52 +0800 -Subject: [PATCH 123/140] Revert JDK-8272873: C2: Inlining should not depend on - absolute call site counts - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index a838a377829..b4f71c45ec1 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -41,6 +41,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap NULLs - define_pd_global(uintx, CodeCacheSegmentSize, 64 TIERED_ONLY(+64)); // Tiered compilation has large code-entry alignment. - define_pd_global(intx, CodeEntryAlignment, 64); - define_pd_global(intx, OptoLoopAlignment, 16); -+define_pd_global(intx, InlineFrequencyCount, 100); - - #define DEFAULT_STACK_YELLOW_PAGES (2) - #define DEFAULT_STACK_RED_PAGES (1) - -From 2df3625eea16fc0d45c0e4cf12c9433f0ec070fd Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 22:02:13 +0800 -Subject: [PATCH 124/140] Revert JDK-8220049: Obsolete ThreadLocalHandshakes - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index b4f71c45ec1..b7d85373c4a 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -76,6 +76,8 @@ define_pd_global(bool, CompactStrings, true); - // Clear short arrays bigger than one word in an arch-specific way - define_pd_global(intx, InitArrayShortSize, BytesPerLong); - -+define_pd_global(bool, ThreadLocalHandshakes, true); -+ - define_pd_global(intx, InlineSmallCode, 1000); - - #define ARCH_FLAGS(develop, \ - -From a875c4caa423dd727cea1c891b17f4ded97e57d1 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sun, 30 Apr 2023 22:04:32 +0800 -Subject: [PATCH 125/140] Revert: JDK-8243208: Clean up JVMFlag implementation - JDK-8236625: Remove writeable macro from JVM flags declaration - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index b7d85373c4a..0becd9efd35 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -82,9 +82,12 @@ define_pd_global(intx, InlineSmallCode, 1000); - - #define ARCH_FLAGS(develop, \ - product, \ -+ diagnostic, \ -+ experimental, \ - notproduct, \ - range, \ -- constraint) \ -+ constraint, \ -+ writeable) \ - \ - product(bool, NearCpool, true, \ - "constant pool is close to instructions") \ - -From 19a9e6e8c3dba77cf8be0f25b1aec394aeca0b25 Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Wed, 10 May 2023 09:44:12 +0800 -Subject: [PATCH 126/140] Revert JDK-8213436: Obsolete UseMembar && - JDK-8188764: Obsolete AssumeMP and then remove all support for non-MP builds, - always enabled - ---- - src/hotspot/cpu/riscv/globals_riscv.hpp | 2 ++ - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp -index 0becd9efd35..e820898d87f 100644 ---- a/src/hotspot/cpu/riscv/globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/globals_riscv.hpp -@@ -64,6 +64,8 @@ define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES); - define_pd_global(bool, RewriteBytecodes, true); - define_pd_global(bool, RewriteFrequentPairs, true); - -+define_pd_global(bool, UseMembar, true); -+ - define_pd_global(bool, PreserveFramePointer, false); - - // GC Ergo Flags -diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -index 50ee7edb708..f13e4269b77 100644 ---- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp -@@ -139,6 +139,8 @@ void VM_Version::initialize() { - #endif // COMPILER2 - - UNSUPPORTED_OPTION(CriticalJNINatives); -+ -+ FLAG_SET_DEFAULT(UseMembar, true); - } - - #ifdef COMPILER2 - -From 0c4a9d1b6b3b3b31a1c105ff311414ae542764bb Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Mon, 1 May 2023 16:04:15 +0800 -Subject: [PATCH 127/140] Misc adaptations to jdk11u - ---- - src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 2 +- - .../linux_riscv/vm_version_linux_riscv.cpp | 16 ++++++++-------- - 2 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -index 25e00bea901..9316d4be02e 100644 ---- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -+++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp -@@ -57,7 +57,7 @@ define_pd_global(uintx, CodeCacheMinBlockLength, 1); - define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); - define_pd_global(uintx, MetaspaceSize, 12*M ); - define_pd_global(bool, NeverActAsServerClassMachine, true ); --define_pd_global(uint64_t, MaxRAM, 1ULL*G); -+define_pd_global(uint64_t, MaxRAM, 1ULL*G); - define_pd_global(bool, CICompileOSR, true ); - #endif // !TIERED - define_pd_global(bool, UseTypeProfile, false); -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 4623dbfad42..60260854db6 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 -@@ -83,14 +83,14 @@ void VM_Version::get_os_cpu_info() { - - uint64_t auxv = getauxval(AT_HWCAP); - -- static_assert(CPU_I == HWCAP_ISA_I, "Flag CPU_I must follow Linux HWCAP"); -- static_assert(CPU_M == HWCAP_ISA_M, "Flag CPU_M must follow Linux HWCAP"); -- static_assert(CPU_A == HWCAP_ISA_A, "Flag CPU_A must follow Linux HWCAP"); -- static_assert(CPU_F == HWCAP_ISA_F, "Flag CPU_F must follow Linux HWCAP"); -- static_assert(CPU_D == HWCAP_ISA_D, "Flag CPU_D must follow Linux HWCAP"); -- static_assert(CPU_C == HWCAP_ISA_C, "Flag CPU_C must follow Linux HWCAP"); -- static_assert(CPU_V == HWCAP_ISA_V, "Flag CPU_V must follow Linux HWCAP"); -- static_assert(CPU_B == HWCAP_ISA_B, "Flag CPU_B must follow Linux HWCAP"); -+ STATIC_ASSERT(CPU_I == HWCAP_ISA_I); -+ STATIC_ASSERT(CPU_M == HWCAP_ISA_M); -+ STATIC_ASSERT(CPU_A == HWCAP_ISA_A); -+ STATIC_ASSERT(CPU_F == HWCAP_ISA_F); -+ STATIC_ASSERT(CPU_D == HWCAP_ISA_D); -+ STATIC_ASSERT(CPU_C == HWCAP_ISA_C); -+ STATIC_ASSERT(CPU_V == HWCAP_ISA_V); -+ STATIC_ASSERT(CPU_B == HWCAP_ISA_B); - _features = auxv & ( - HWCAP_ISA_I | - HWCAP_ISA_M | - -From 4ce5e05526029360ad15eb9639c9c05fac77ac8e Mon Sep 17 00:00:00 2001 -From: "yunyao.zxl" -Date: Sat, 20 May 2023 17:51:52 +0800 -Subject: [PATCH 128/140] Save all call-clobbered registers for spark tests may - crash - ---- - .../cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp | 10 ++-------- - 1 file changed, 2 insertions(+), 8 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -index bc847388f68..e191cbcee2a 100644 ---- a/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -157,21 +157,15 @@ void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, - __ j(done); - - __ bind(runtime); -- // save the live input values -- RegSet saved = RegSet::of(pre_val); -- if (tosca_live) { saved += RegSet::of(x10); } -- if (obj != noreg) { saved += RegSet::of(obj); } -- -- __ push_reg(saved, sp); - -+ __ push_call_clobbered_registers(); - if (expand_call) { - assert(pre_val != c_rarg1, "smashed arg"); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); - } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread); - } -- -- __ pop_reg(saved, sp); -+ __ pop_call_clobbered_registers(); - - __ bind(done); - - -From 1b8778b0831571e9ac688bbd22afca4cf8f62407 Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Tue, 22 Aug 2023 16:17:31 +0800 -Subject: [PATCH 129/140] Build with gcc 13 - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 1 + - src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp | 1 + - 2 files changed, 2 insertions(+) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 37ccf132986..fd18bb77058 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -49,6 +49,7 @@ - #include "runtime/thread.hpp" - #ifdef COMPILER2 - #include "opto/compile.hpp" -+#include "opto/intrinsicnode.hpp" - #include "opto/node.hpp" - #include "opto/output.hpp" - #endif -diff --git a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -index 31d9254d8ad..ccceed643ed 100644 ---- a/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -+++ b/src/hotspot/os_cpu/linux_riscv/thread_linux_riscv.cpp -@@ -24,6 +24,7 @@ - */ - - #include "precompiled.hpp" -+#include "memory/metaspaceShared.hpp" - #include "runtime/frame.inline.hpp" - #include "runtime/thread.inline.hpp" - - -From 4c23be6665aec94462e82e3b4adcf7abb5b23981 Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Tue, 5 Sep 2023 15:37:43 +0800 -Subject: [PATCH 130/140] Fix copyright information - ---- - make/autoconf/build-aux/config.guess | 2 +- - .../MyPackage/HeapMonitorEventsForTwoThreadsTest.java | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/make/autoconf/build-aux/config.guess b/make/autoconf/build-aux/config.guess -index 15111d827ab..a88a9adec3f 100644 ---- a/make/autoconf/build-aux/config.guess -+++ b/make/autoconf/build-aux/config.guess -@@ -1,6 +1,6 @@ - #!/bin/sh - # --# Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. -+# Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. - # Copyright (c) 2021, Azul Systems, Inc. All rights reserved. - # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - # -diff --git a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -index f0b7aed5ceb..54640b245f8 100644 ---- a/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -+++ b/test/hotspot/jtreg/serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorEventsForTwoThreadsTest.java -@@ -1,4 +1,5 @@ - /* -+ * Copyright (c) 2018, Google 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 - -From 70a060f73c3617e58f881bcee19f1a3ce43f54ff Mon Sep 17 00:00:00 2001 -From: Chris Plummer -Date: Thu, 2 Jul 2020 13:13:10 -0700 -Subject: [PATCH 131/140] 8247533: SA stack walking sometimes fails with - sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp - -Reviewed-by: sspitsyn, ysuenaga, dtitov ---- - .../native/libsaproc/LinuxDebuggerLocal.c | 8 ++++++- - .../linux/native/libsaproc/ps_proc.c | 3 ++- - .../native/libsaproc/MacosxDebuggerLocal.m | 24 ++++++++++++------- - .../debugger/bsd/BsdDebuggerLocal.java | 2 +- - .../jvm/hotspot/debugger/bsd/BsdThread.java | 10 +++++--- - .../debugger/linux/LinuxDebuggerLocal.java | 2 +- - .../hotspot/debugger/linux/LinuxThread.java | 10 +++++--- - .../windbg/amd64/WindbgAMD64Thread.java | 15 ++++++++---- - .../windows/native/libsaproc/sawindbg.cpp | 14 ++++++++--- - 9 files changed, 61 insertions(+), 27 deletions(-) - -diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -index 45a927fb5ee..6f1887f8113 100644 ---- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -@@ -413,7 +413,13 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo - - struct ps_prochandle* ph = get_proc_handle(env, this_obj); - if (get_lwp_regs(ph, lwp_id, &gregs) != true) { -- THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); -+ // This is not considered fatal and does happen on occassion, usually with an -+ // ESRCH error. The root cause is not fully understood, but by ignoring this error -+ // and returning NULL, stacking walking code will get null registers and fallback -+ // to using the "last java frame" if setup. -+ fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: get_lwp_regs failed for lwp (%d)\n", lwp_id); -+ fflush(stdout); -+ return NULL; - } - - #undef NPRGREG -diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -index de5254d859e..691c3f6684a 100644 ---- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -@@ -144,7 +144,8 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use - - #ifdef PTRACE_GETREGS_REQ - if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { -- print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid); -+ print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp(%d) errno(%d) \"%s\"\n", pid, -+ errno, strerror(errno)); - return false; - } - return true; -diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -index 18b8b4282fe..e46370a1f18 100644 ---- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -@@ -685,7 +685,7 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - JNIEnv *env, jobject this_obj, - jlong thread_id) - { -- print_debug("getThreadRegisterSet0 called\n"); -+ print_debug("getThreadIntegerRegisterSet0 called\n"); - - struct ps_prochandle* ph = get_proc_handle(env, this_obj); - if (ph != NULL && ph->core != NULL) { -@@ -705,7 +705,13 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); - - if (result != KERN_SUCCESS) { -- print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result); -+ // This is not considered fatal. Unlike on Linux and Windows, we haven't seen a -+ // failure to get thread registers, but if it were to fail the response should -+ // be the same. By ignoring this error and returning NULL, stacking walking code -+ // will get null registers and fallback to using the "last java frame" if setup. -+ fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: thread_get_state failed (%d) for thread (%d)\n", -+ result, tid); -+ fflush(stdout); - return NULL; - } - -@@ -808,25 +814,25 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - */ - JNIEXPORT jint JNICALL - Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( -- JNIEnv *env, jobject this_obj, jint tid) -+ JNIEnv *env, jobject this_obj, jint tid) - { - print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); - - kern_return_t result; - thread_t foreign_tid, usable_tid; - mach_msg_type_name_t type; -- -+ - foreign_tid = tid; -- -+ - task_t gTask = getTask(env, this_obj); -- result = mach_port_extract_right(gTask, foreign_tid, -- MACH_MSG_TYPE_COPY_SEND, -+ result = mach_port_extract_right(gTask, foreign_tid, -+ MACH_MSG_TYPE_COPY_SEND, - &usable_tid, &type); - if (result != KERN_SUCCESS) - return -1; -- -+ - print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); -- -+ - return (jint) usable_tid; - } - -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -index 655b450c3fc..d0557a7d254 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -@@ -166,7 +166,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException - } catch (InterruptedException x) {} - } - if (lastException != null) { -- throw new DebuggerException(lastException); -+ throw new DebuggerException(lastException.getMessage(), lastException); - } else { - return task; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -index 0d637f30f14..c52d3a51d54 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2002, 2020, 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 -@@ -67,8 +67,12 @@ public String toString() { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id); - ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -+ // null means we failed to get the register set for some reason. The caller -+ // is responsible for dealing with the set of null registers in that case. -+ if (data != null) { -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); -+ } - } - return context; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -index cb6712b58ee..6a0648f508a 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -@@ -173,7 +173,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException - } catch (InterruptedException x) {} - } - if (lastException != null) { -- throw new DebuggerException(lastException); -+ throw new DebuggerException(lastException.getMessage(), lastException); - } else { - return task; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -index 52307b9cdcf..3fe795d34bc 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2002, 2020, 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 -@@ -73,8 +73,12 @@ public String toString() { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); - ThreadContext context = LinuxThreadContextFactory.createThreadContext(debugger); -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -+ // null means we failed to get the register set for some reason. The caller -+ // is responsible for dealing with the set of null registers in that case. -+ if (data != null) { -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); -+ } - } - return context; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -index ec5aea35e8c..377650a0a1c 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -30,9 +30,9 @@ - - class WindbgAMD64Thread implements ThreadProxy { - private WindbgDebugger debugger; -- private long sysId; -+ private long sysId; // SystemID for Windows thread, stored in OSThread::_thread_id - private boolean gotID; -- private long id; -+ private long id; // ThreadID for Windows thread, returned by GetThreadIdBySystemId - - // The address argument must be the address of the OSThread::_thread_id - WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { -@@ -50,8 +50,12 @@ class WindbgAMD64Thread implements ThreadProxy { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(getThreadID()); - WindbgAMD64ThreadContext context = new WindbgAMD64ThreadContext(debugger); -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -+ // null means we failed to get the register set for some reason. The caller -+ // is responsible for dealing with the set of null registers in that case. -+ if (data != null) { -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); -+ } - } - return context; - } -@@ -86,6 +90,7 @@ public String toString() { - private long getThreadID() { - if (!gotID) { - id = debugger.getThreadIdFromSysId(sysId); -+ gotID = true; - } - - return id; -diff --git a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -index 314cf69c957..e3b218b4dae 100644 ---- a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -+++ b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -@@ -45,6 +45,7 @@ - - #include - #include -+#include - - #define DEBUG_NO_IMPLEMENTATION - #include -@@ -765,9 +766,16 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal - CHECK_EXCEPTION_(0); - - ULONG id = 0; -- COM_VERIFY_OK_(ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id), -- "Windbg Error: GetThreadIdBySystemId failed!", 0); -- -+ HRESULT hr = ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id); -+ if (hr != S_OK) { -+ // This is not considered fatal and does happen on occassion, usually with an -+ // 0x80004002 "No such interface supported". The root cause is not fully understood, -+ // but by ignoring this error and returning NULL, stacking walking code will get -+ // null registers and fallback to using the "last java frame" if setup. -+ printf("WARNING: GetThreadIdBySystemId failed with 0x%x for sysId (%" PRIu64 ")\n", -+ hr, sysId); -+ return -1; -+ } - return (jlong) id; - } - - -From 2cadd133d25e05be6ab9b16024a37bed79af1f15 Mon Sep 17 00:00:00 2001 -From: Xiaolin Zheng -Date: Wed, 30 Mar 2022 09:04:55 +0000 -Subject: [PATCH 132/140] 8283737: riscv: MacroAssembler::stop() should emit - fixed-length instruction sequence - -Reviewed-by: fyang, shade ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index fd18bb77058..b72a553da2f 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -542,8 +542,11 @@ void MacroAssembler::resolve_jobject(Register value, Register thread, Register t - void MacroAssembler::stop(const char* msg) { - address ip = pc(); - pusha(); -- li(c_rarg0, (uintptr_t)(address)msg); -- li(c_rarg1, (uintptr_t)(address)ip); -+ // The length of the instruction sequence emitted should be independent -+ // of the values of msg and ip so that the size of mach nodes for scratch -+ // emit and normal emit matches. -+ mv(c_rarg0, (address)msg); -+ mv(c_rarg1, (address)ip); - mv(c_rarg2, sp); - mv(c_rarg3, CAST_FROM_FN_PTR(address, MacroAssembler::debug64)); - jalr(c_rarg3); - -From 729e0db14cb320aedf1f12051e667513bddbb8e8 Mon Sep 17 00:00:00 2001 -From: Xiaolin Zheng -Date: Sun, 24 Apr 2022 02:17:03 +0000 -Subject: [PATCH 133/140] 8285437: riscv: Fix MachNode size mismatch for - MacroAssembler::verify_oops* - -Reviewed-by: shade, fyang ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index b72a553da2f..9f80f7e2650 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -389,7 +389,10 @@ void MacroAssembler::verify_oop(Register reg, const char* s) { - push_reg(RegSet::of(ra, t0, t1, c_rarg0), sp); - - mv(c_rarg0, reg); // c_rarg0 : x10 -- li(t0, (uintptr_t)(address)b); -+ // The length of the instruction sequence emitted should be independent -+ // of the values of the local char buffer address so that the size of mach -+ // nodes for scratch emit and normal emit matches. -+ mv(t0, (address)b); - - // call indirectly to solve generation ordering problem - int32_t offset = 0; -@@ -425,7 +428,10 @@ void MacroAssembler::verify_oop_addr(Address addr, const char* s) { - ld(x10, addr); - } - -- li(t0, (uintptr_t)(address)b); -+ // The length of the instruction sequence emitted should be independent -+ // of the values of the local char buffer address so that the size of mach -+ // nodes for scratch emit and normal emit matches. -+ mv(t0, (address)b); - - // call indirectly to solve generation ordering problem - int32_t offset = 0; - -From 5cab06c6f09f4b62d54d8d291b1a23f796a085c1 Mon Sep 17 00:00:00 2001 -From: Xiaolin Zheng -Date: Mon, 30 May 2022 07:45:50 +0000 -Subject: [PATCH 134/140] 8287418: riscv: Fix correctness issue of - MacroAssembler::movptr - -Reviewed-by: fjiang, yadongwang, fyang ---- - src/hotspot/cpu/riscv/assembler_riscv.cpp | 14 +++++++------- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 18 +++++++++--------- - src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 3 ++- - src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 2 +- - 4 files changed, 19 insertions(+), 18 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp -index f15ef5304c5..a5f688cda1f 100644 ---- a/src/hotspot/cpu/riscv/assembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp -@@ -282,9 +282,9 @@ void Assembler::movptr_with_offset(Register Rd, address addr, int32_t &offset) { - } - #endif - assert(is_unsigned_imm_in_range(imm64, 47, 0) || (imm64 == (uintptr_t)-1), -- "48-bit overflow in address constant"); -- // Load upper 32 bits -- int32_t imm = imm64 >> 16; -+ "bit 47 overflows in address constant"); -+ // Load upper 31 bits -+ int32_t imm = imm64 >> 17; - int64_t upper = imm, lower = imm; - lower = (lower << 52) >> 52; - upper -= lower; -@@ -292,13 +292,13 @@ void Assembler::movptr_with_offset(Register Rd, address addr, int32_t &offset) { - lui(Rd, upper); - addi(Rd, Rd, lower); - -- // Load the rest 16 bits. -+ // Load the rest 17 bits. - slli(Rd, Rd, 11); -- addi(Rd, Rd, (imm64 >> 5) & 0x7ff); -- slli(Rd, Rd, 5); -+ addi(Rd, Rd, (imm64 >> 6) & 0x7ff); -+ slli(Rd, Rd, 6); - - // This offset will be used by following jalr/ld. -- offset = imm64 & 0x1f; -+ offset = imm64 & 0x3f; - } - - void Assembler::movptr(Register Rd, uintptr_t imm64) { -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index 9f80f7e2650..f592d7585da 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1158,12 +1158,12 @@ static int patch_offset_in_pc_relative(address branch, int64_t offset) { - - static int patch_addr_in_movptr(address branch, address target) { - const int MOVPTR_INSTRUCTIONS_NUM = 6; // lui + addi + slli + addi + slli + addi/jalr/load -- int32_t lower = ((intptr_t)target << 36) >> 36; -- int64_t upper = ((intptr_t)target - lower) >> 28; -- Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[47:28] + target[27] ==> branch[31:12] -- Assembler::patch(branch + 4, 31, 20, (lower >> 16) & 0xfff); // Addi. target[27:16] ==> branch[31:20] -- Assembler::patch(branch + 12, 31, 20, (lower >> 5) & 0x7ff); // Addi. target[15: 5] ==> branch[31:20] -- Assembler::patch(branch + 20, 31, 20, lower & 0x1f); // Addi/Jalr/Load. target[ 4: 0] ==> branch[31:20] -+ int32_t lower = ((intptr_t)target << 35) >> 35; -+ int64_t upper = ((intptr_t)target - lower) >> 29; -+ Assembler::patch(branch + 0, 31, 12, upper & 0xfffff); // Lui. target[48:29] + target[28] ==> branch[31:12] -+ Assembler::patch(branch + 4, 31, 20, (lower >> 17) & 0xfff); // Addi. target[28:17] ==> branch[31:20] -+ Assembler::patch(branch + 12, 31, 20, (lower >> 6) & 0x7ff); // Addi. target[16: 6] ==> branch[31:20] -+ Assembler::patch(branch + 20, 31, 20, lower & 0x3f); // Addi/Jalr/Load. target[ 5: 0] ==> branch[31:20] - return MOVPTR_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; - } - -@@ -1235,9 +1235,9 @@ static long get_offset_of_pc_relative(address insn_addr) { - - static address get_target_of_movptr(address insn_addr) { - assert_cond(insn_addr != NULL); -- intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 28; // Lui. -- target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 16; // Addi. -- target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 5; // Addi. -+ intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 29; // Lui. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)) << 17; // Addi. -+ target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[3], 31, 20)) << 6; // Addi. - target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[5], 31, 20)); // Addi/Jalr/Load. - return (address) target_address; - } -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 45ffc663963..792c1fc2103 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -827,7 +827,8 @@ class MacroAssembler: public Assembler { - - // Return true if an address is within the 48-bit RISCV64 address space. - bool is_valid_riscv64_address(address addr) { -- return ((uintptr_t)addr >> 48) == 0; -+ // sv48: must have bits 63–48 all equal to bit 47 -+ return ((uintptr_t)addr >> 47) == 0; - } - - void ld_constant(Register dest, const Address &const_addr) { -diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -index bfe84fa4e30..27011ad1283 100644 ---- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -+++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -@@ -89,7 +89,7 @@ bool NativeInstruction::is_movptr_at(address instr) { - is_addi_at(instr + instruction_size) && // Addi - is_slli_shift_at(instr + instruction_size * 2, 11) && // Slli Rd, Rs, 11 - is_addi_at(instr + instruction_size * 3) && // Addi -- is_slli_shift_at(instr + instruction_size * 4, 5) && // Slli Rd, Rs, 5 -+ is_slli_shift_at(instr + instruction_size * 4, 6) && // Slli Rd, Rs, 6 - (is_addi_at(instr + instruction_size * 5) || - is_jalr_at(instr + instruction_size * 5) || - is_load_at(instr + instruction_size * 5)) && // Addi/Jalr/Load - -From 41d73298bf28473b3ba2483e61a39c188eddfde3 Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Fri, 22 Sep 2023 16:57:56 +0800 -Subject: [PATCH 135/140] Fix: Fixed-length mv() mistakenly redirected to li() - during reshaping - ---- - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 6 ++++++ - src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 3 +-- - 2 files changed, 7 insertions(+), 2 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -index f592d7585da..f851cc1e413 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -1343,6 +1343,12 @@ void MacroAssembler::mv(Register Rd, Address dest) { - movptr(Rd, dest.target()); - } - -+void MacroAssembler::mv(Register Rd, address addr) { -+ // Here in case of use with relocation, use fix length instruction -+ // movptr instead of li -+ movptr(Rd, addr); -+} -+ - void MacroAssembler::mv(Register Rd, RegisterOrConstant src) { - if (src.is_register()) { - mv(Rd, src.as_register()); -diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -index 792c1fc2103..65f91532661 100644 ---- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -540,8 +540,6 @@ class MacroAssembler: public Assembler { - } - - // mv -- void mv(Register Rd, address addr) { li(Rd, (int64_t)addr); } -- - inline void mv(Register Rd, int imm64) { li(Rd, (int64_t)imm64); } - inline void mv(Register Rd, long imm64) { li(Rd, (int64_t)imm64); } - inline void mv(Register Rd, long long imm64) { li(Rd, (int64_t)imm64); } -@@ -552,6 +550,7 @@ class MacroAssembler: public Assembler { - inline void mvw(Register Rd, int32_t imm32) { mv(Rd, imm32); } - - void mv(Register Rd, Address dest); -+ void mv(Register Rd, address dest); - void mv(Register Rd, RegisterOrConstant src); - - // logic - -From 26f4b26a98507ec03a2329bfcbaab393247fe83f Mon Sep 17 00:00:00 2001 -From: Xiaolin Zheng -Date: Fri, 2 Sep 2022 07:01:02 +0000 -Subject: [PATCH 136/140] 8293100: RISC-V: Need to save and restore - callee-saved FloatRegisters in StubGenerator::generate_call_stub - -Reviewed-by: yadongwang, fjiang, shade, vkempik ---- - src/hotspot/cpu/riscv/frame_riscv.hpp | 2 +- - src/hotspot/cpu/riscv/riscv.ad | 18 ++--- - src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 74 +++++++++++++++++-- - src/hotspot/cpu/riscv/vmreg_riscv.cpp | 2 +- - 4 files changed, 80 insertions(+), 16 deletions(-) - -diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp -index 3b88f6d5a1a..18e021dcb94 100644 ---- a/src/hotspot/cpu/riscv/frame_riscv.hpp -+++ b/src/hotspot/cpu/riscv/frame_riscv.hpp -@@ -131,7 +131,7 @@ - // Entry frames - // n.b. these values are determined by the layout defined in - // stubGenerator for the Java call stub -- entry_frame_after_call_words = 22, -+ entry_frame_after_call_words = 34, - entry_frame_call_wrapper_offset = -10, - - // we don't need a save area -diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad -index e410bd06aa6..69696b272a5 100644 ---- a/src/hotspot/cpu/riscv/riscv.ad -+++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -8601,7 +8601,7 @@ instruct cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST); -- format %{ "float_b$cmp $op1, $op2 \t#@cmpF_branch"%} -+ format %{ "float_b$cmp $op1, $op2, $lbl \t#@cmpF_branch"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); -@@ -8618,7 +8618,7 @@ instruct cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST); -- format %{ "float_b$cmp $op1, $op2\t#@cmpF_loop"%} -+ format %{ "float_b$cmp $op1, $op2, $lbl\t#@cmpF_loop"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), *($lbl$$label)); -@@ -8636,7 +8636,7 @@ instruct cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST); -- format %{ "double_b$cmp $op1, $op2\t#@cmpD_branch"%} -+ format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_branch"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -@@ -8654,7 +8654,7 @@ instruct cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST); -- format %{ "double_b$cmp $op1, $op2\t#@cmpD_loop"%} -+ format %{ "double_b$cmp $op1, $op2, $lbl\t#@cmpD_loop"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -@@ -8929,7 +8929,7 @@ instruct far_cmpFlag_branch(cmpOp cmp, rFlagsReg cr, label lbl) %{ - effect(USE lbl); - - ins_cost(BRANCH_COST); -- format %{ "far_b$cmp $cr, zr, L\t#@far_cmpFlag_branch"%} -+ format %{ "far_b$cmp $cr, zr, $lbl\t#@far_cmpFlag_branch"%} - - ins_encode %{ - __ enc_cmpEqNe_imm0_branch($cmp$$cmpcode, as_Register($cr$$reg), *($lbl$$label), /* is_far */ true); -@@ -9138,7 +9138,7 @@ instruct far_cmpF_branch(cmpOp cmp, fRegF op1, fRegF op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST * 2); -- format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_branch"%} -+ format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_branch"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), -@@ -9154,7 +9154,7 @@ instruct far_cmpF_loop(cmpOp cmp, fRegF op1, fRegF op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST * 2); -- format %{ "far_float_b$cmp $op1, $op2\t#@far_cmpF_loop"%} -+ format %{ "far_float_b$cmp $op1, $op2, $lbl\t#@far_cmpF_loop"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode, as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), -@@ -9171,7 +9171,7 @@ instruct far_cmpD_branch(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST * 2); -- format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_branch"%} -+ format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_branch"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -@@ -9187,7 +9187,7 @@ instruct far_cmpD_loop(cmpOp cmp, fRegD op1, fRegD op2, label lbl) - effect(USE lbl); - - ins_cost(XFER_COST + BRANCH_COST * 2); -- format %{ "far_double_b$cmp $op1, $op2\t#@far_cmpD_loop"%} -+ format %{ "far_double_b$cmp $op1, $op2, $lbl\t#@far_cmpD_loop"%} - - ins_encode %{ - __ float_cmp_branch($cmp$$cmpcode | MacroAssembler::double_branch_mask, as_FloatRegister($op1$$reg), -diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -index 74c38c3d044..9970229c5c5 100644 ---- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp -@@ -118,16 +118,28 @@ class StubGenerator: public StubCodeGenerator { - // we don't need to save x6-x7 and x28-x31 which both C and Java treat as - // volatile - // -- // we save x18-x27 which Java uses as temporary registers and C -- // expects to be callee-save -+ // we save x9, x18-x27, f8-f9, and f18-f27 which Java uses as temporary -+ // registers and C expects to be callee-save - // - // so the stub frame looks like this when we enter Java code - // - // [ return_from_Java ] <--- sp - // [ argument word n ] - // ... -- // -22 [ argument word 1 ] -- // -21 [ saved x27 ] <--- sp_after_call -+ // -34 [ argument word 1 ] -+ // -33 [ saved f27 ] <--- sp_after_call -+ // -32 [ saved f26 ] -+ // -31 [ saved f25 ] -+ // -30 [ saved f24 ] -+ // -29 [ saved f23 ] -+ // -28 [ saved f22 ] -+ // -27 [ saved f21 ] -+ // -26 [ saved f20 ] -+ // -25 [ saved f19 ] -+ // -24 [ saved f18 ] -+ // -23 [ saved f9 ] -+ // -22 [ saved f8 ] -+ // -21 [ saved x27 ] - // -20 [ saved x26 ] - // -19 [ saved x25 ] - // -18 [ saved x24 ] -@@ -152,7 +164,20 @@ class StubGenerator: public StubCodeGenerator { - - // Call stub stack layout word offsets from fp - enum call_stub_layout { -- sp_after_call_off = -21, -+ sp_after_call_off = -33, -+ -+ f27_off = -33, -+ f26_off = -32, -+ f25_off = -31, -+ f24_off = -30, -+ f23_off = -29, -+ f22_off = -28, -+ f21_off = -27, -+ f20_off = -26, -+ f19_off = -25, -+ f18_off = -24, -+ f9_off = -23, -+ f8_off = -22, - - x27_off = -21, - x26_off = -20, -@@ -198,6 +223,19 @@ class StubGenerator: public StubCodeGenerator { - - const Address thread (fp, thread_off * wordSize); - -+ const Address f27_save (fp, f27_off * wordSize); -+ const Address f26_save (fp, f26_off * wordSize); -+ const Address f25_save (fp, f25_off * wordSize); -+ const Address f24_save (fp, f24_off * wordSize); -+ const Address f23_save (fp, f23_off * wordSize); -+ const Address f22_save (fp, f22_off * wordSize); -+ const Address f21_save (fp, f21_off * wordSize); -+ const Address f20_save (fp, f20_off * wordSize); -+ const Address f19_save (fp, f19_off * wordSize); -+ const Address f18_save (fp, f18_off * wordSize); -+ const Address f9_save (fp, f9_off * wordSize); -+ const Address f8_save (fp, f8_off * wordSize); -+ - const Address x27_save (fp, x27_off * wordSize); - const Address x26_save (fp, x26_off * wordSize); - const Address x25_save (fp, x25_off * wordSize); -@@ -244,6 +282,19 @@ class StubGenerator: public StubCodeGenerator { - __ sd(x26, x26_save); - __ sd(x27, x27_save); - -+ __ fsd(f8, f8_save); -+ __ fsd(f9, f9_save); -+ __ fsd(f18, f18_save); -+ __ fsd(f19, f19_save); -+ __ fsd(f20, f20_save); -+ __ fsd(f21, f21_save); -+ __ fsd(f22, f22_save); -+ __ fsd(f23, f23_save); -+ __ fsd(f24, f24_save); -+ __ fsd(f25, f25_save); -+ __ fsd(f26, f26_save); -+ __ fsd(f27, f27_save); -+ - // install Java thread in global register now we have saved - // whatever value it held - __ mv(xthread, c_rarg7); -@@ -335,6 +386,19 @@ class StubGenerator: public StubCodeGenerator { - #endif - - // restore callee-save registers -+ __ fld(f27, f27_save); -+ __ fld(f26, f26_save); -+ __ fld(f25, f25_save); -+ __ fld(f24, f24_save); -+ __ fld(f23, f23_save); -+ __ fld(f22, f22_save); -+ __ fld(f21, f21_save); -+ __ fld(f20, f20_save); -+ __ fld(f19, f19_save); -+ __ fld(f18, f18_save); -+ __ fld(f9, f9_save); -+ __ fld(f8, f8_save); -+ - __ ld(x27, x27_save); - __ ld(x26, x26_save); - __ ld(x25, x25_save); -diff --git a/src/hotspot/cpu/riscv/vmreg_riscv.cpp b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -index 5d1187c2a27..c4338715f95 100644 ---- a/src/hotspot/cpu/riscv/vmreg_riscv.cpp -+++ b/src/hotspot/cpu/riscv/vmreg_riscv.cpp -@@ -40,7 +40,7 @@ void VMRegImpl::set_regName() { - FloatRegister freg = ::as_FloatRegister(0); - for ( ; i < ConcreteRegisterImpl::max_fpr ; ) { - for (int j = 0 ; j < FloatRegisterImpl::max_slots_per_register ; j++) { -- regName[i++] = reg->name(); -+ regName[i++] = freg->name(); - } - freg = freg->successor(); - } - -From 69ea557c320ad7b2f35fc0e986af9b485f95addf Mon Sep 17 00:00:00 2001 -From: Xiaolin Zheng -Date: Fri, 28 Oct 2022 11:56:21 +0000 -Subject: [PATCH 137/140] 8295926: RISC-V: C1: Fix - LIRGenerator::do_LibmIntrinsic - -Reviewed-by: yadongwang, fyang ---- - .../cpu/riscv/c1_LIRGenerator_riscv.cpp | 21 +++-- - .../floatingpoint/TestLibmIntrinsics.java | 80 +++++++++++++++++++ - 2 files changed, 96 insertions(+), 5 deletions(-) - create mode 100644 test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java - -diff --git a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -index f9242251491..c41819fc2ae 100644 ---- a/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -+++ b/src/hotspot/cpu/riscv/c1_LIRGenerator_riscv.cpp -@@ -679,19 +679,30 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { - void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) { - LIRItem value(x->argument_at(0), this); - value.set_destroys_register(); -+ - LIR_Opr calc_result = rlock_result(x); - LIR_Opr result_reg = result_register_for(x->type()); -+ - CallingConvention* cc = NULL; -- BasicTypeList signature(1); -- signature.append(T_DOUBLE); -- if (x->id() == vmIntrinsics::_dpow) { signature.append(T_DOUBLE); } -- cc = frame_map()->c_calling_convention(&signature); -- value.load_item_force(cc->at(0)); -+ - if (x->id() == vmIntrinsics::_dpow) { - LIRItem value1(x->argument_at(1), this); -+ - value1.set_destroys_register(); -+ -+ BasicTypeList signature(2); -+ signature.append(T_DOUBLE); -+ signature.append(T_DOUBLE); -+ cc = frame_map()->c_calling_convention(&signature); -+ value.load_item_force(cc->at(0)); - value1.load_item_force(cc->at(1)); -+ } else { -+ BasicTypeList signature(1); -+ signature.append(T_DOUBLE); -+ cc = frame_map()->c_calling_convention(&signature); -+ value.load_item_force(cc->at(0)); - } -+ - switch (x->id()) { - case vmIntrinsics::_dexp: - if (StubRoutines::dexp() != NULL) { __ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args()); } -diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java -new file mode 100644 -index 00000000000..5c711efddea ---- /dev/null -+++ b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java -@@ -0,0 +1,80 @@ -+/* -+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2022, Alibaba Group Holding Limited. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ */ -+ -+/* -+ * @test -+ * @summary Test libm intrinsics -+ * @library /test/lib / -+ * -+ * @build jdk.test.whitebox.WhiteBox -+ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox -+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -+ * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -+ * compiler.floatingpoint.TestLibmIntrinsics -+ */ -+ -+package compiler.floatingpoint; -+ -+import compiler.whitebox.CompilerWhiteBoxTest; -+import jdk.test.whitebox.WhiteBox; -+ -+import java.lang.reflect.Method; -+ -+public class TestLibmIntrinsics { -+ -+ private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); -+ -+ private static final double pi = 3.1415926; -+ -+ private static final double expected = 2.5355263553695413; -+ -+ static double m() { -+ return Math.pow(pi, Math.sin(Math.cos(Math.tan(Math.log(Math.log10(Math.exp(pi))))))); -+ } -+ -+ static public void main(String[] args) throws NoSuchMethodException { -+ Method test_method = compiler.floatingpoint.TestLibmIntrinsics.class.getDeclaredMethod("m"); -+ -+ double interpreter_result = m(); -+ -+ // Compile with C1 if possible -+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); -+ -+ double c1_result = m(); -+ -+ WHITE_BOX.deoptimizeMethod(test_method); -+ -+ // Compile it with C2 if possible -+ WHITE_BOX.enqueueMethodForCompilation(test_method, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION); -+ -+ double c2_result = m(); -+ -+ if (interpreter_result != c1_result || -+ interpreter_result != c2_result || -+ c1_result != c2_result) { -+ System.out.println("interpreter = " + interpreter_result + " c1 = " + c1_result + " c2 = " + c2_result); -+ throw new RuntimeException("Test Failed"); -+ } -+ } -+} - -From ec57f23aa4001315a030cacd55aa5ef7c3269fbb Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Mon, 9 Oct 2023 11:07:34 +0800 -Subject: [PATCH 138/140] Fix test error after port 8295926 - ---- - .../jtreg/compiler/floatingpoint/TestLibmIntrinsics.java | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java -index 5c711efddea..5a1b659bbe0 100644 ---- a/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java -+++ b/test/hotspot/jtreg/compiler/floatingpoint/TestLibmIntrinsics.java -@@ -27,8 +27,8 @@ - * @summary Test libm intrinsics - * @library /test/lib / - * -- * @build jdk.test.whitebox.WhiteBox -- * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox -+ * @build sun.hotspot.WhiteBox -+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement - * compiler.floatingpoint.TestLibmIntrinsics -@@ -37,7 +37,7 @@ - package compiler.floatingpoint; - - import compiler.whitebox.CompilerWhiteBoxTest; --import jdk.test.whitebox.WhiteBox; -+import sun.hotspot.WhiteBox; - - import java.lang.reflect.Method; - - -From b115ec4381ad3ad8cbe9ca3d225cb438538916ac Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Tue, 17 Oct 2023 14:22:49 +0800 -Subject: [PATCH 139/140] Revert JDK-8247533: SA stack walking sometimes fails - with sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a - lwp - ---- - .../native/libsaproc/LinuxDebuggerLocal.c | 8 +------ - .../linux/native/libsaproc/ps_proc.c | 3 +-- - .../native/libsaproc/MacosxDebuggerLocal.m | 24 +++++++------------ - .../debugger/bsd/BsdDebuggerLocal.java | 2 +- - .../jvm/hotspot/debugger/bsd/BsdThread.java | 10 +++----- - .../debugger/linux/LinuxDebuggerLocal.java | 2 +- - .../hotspot/debugger/linux/LinuxThread.java | 10 +++----- - .../windbg/amd64/WindbgAMD64Thread.java | 15 ++++-------- - .../windows/native/libsaproc/sawindbg.cpp | 14 +++-------- - 9 files changed, 27 insertions(+), 61 deletions(-) - -diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -index 6f1887f8113..45a927fb5ee 100644 ---- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.c -@@ -413,13 +413,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo - - struct ps_prochandle* ph = get_proc_handle(env, this_obj); - if (get_lwp_regs(ph, lwp_id, &gregs) != true) { -- // This is not considered fatal and does happen on occassion, usually with an -- // ESRCH error. The root cause is not fully understood, but by ignoring this error -- // and returning NULL, stacking walking code will get null registers and fallback -- // to using the "last java frame" if setup. -- fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: get_lwp_regs failed for lwp (%d)\n", lwp_id); -- fflush(stdout); -- return NULL; -+ THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); - } - - #undef NPRGREG -diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -index 691c3f6684a..de5254d859e 100644 ---- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -@@ -144,8 +144,7 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use - - #ifdef PTRACE_GETREGS_REQ - if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { -- print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp(%d) errno(%d) \"%s\"\n", pid, -- errno, strerror(errno)); -+ print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid); - return false; - } - return true; -diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -index e46370a1f18..18b8b4282fe 100644 ---- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m -@@ -685,7 +685,7 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - JNIEnv *env, jobject this_obj, - jlong thread_id) - { -- print_debug("getThreadIntegerRegisterSet0 called\n"); -+ print_debug("getThreadRegisterSet0 called\n"); - - struct ps_prochandle* ph = get_proc_handle(env, this_obj); - if (ph != NULL && ph->core != NULL) { -@@ -705,13 +705,7 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); - - if (result != KERN_SUCCESS) { -- // This is not considered fatal. Unlike on Linux and Windows, we haven't seen a -- // failure to get thread registers, but if it were to fail the response should -- // be the same. By ignoring this error and returning NULL, stacking walking code -- // will get null registers and fallback to using the "last java frame" if setup. -- fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: thread_get_state failed (%d) for thread (%d)\n", -- result, tid); -- fflush(stdout); -+ print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result); - return NULL; - } - -@@ -814,25 +808,25 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo - */ - JNIEXPORT jint JNICALL - Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( -- JNIEnv *env, jobject this_obj, jint tid) -+ JNIEnv *env, jobject this_obj, jint tid) - { - print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); - - kern_return_t result; - thread_t foreign_tid, usable_tid; - mach_msg_type_name_t type; -- -+ - foreign_tid = tid; -- -+ - task_t gTask = getTask(env, this_obj); -- result = mach_port_extract_right(gTask, foreign_tid, -- MACH_MSG_TYPE_COPY_SEND, -+ result = mach_port_extract_right(gTask, foreign_tid, -+ MACH_MSG_TYPE_COPY_SEND, - &usable_tid, &type); - if (result != KERN_SUCCESS) - return -1; -- -+ - print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); -- -+ - return (jint) usable_tid; - } - -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -index d0557a7d254..655b450c3fc 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java -@@ -166,7 +166,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException - } catch (InterruptedException x) {} - } - if (lastException != null) { -- throw new DebuggerException(lastException.getMessage(), lastException); -+ throw new DebuggerException(lastException); - } else { - return task; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -index c52d3a51d54..0d637f30f14 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2002, 2013, 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 -@@ -67,12 +67,8 @@ public String toString() { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id); - ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); -- // null means we failed to get the register set for some reason. The caller -- // is responsible for dealing with the set of null registers in that case. -- if (data != null) { -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -- } -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); - } - return context; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -index 6a0648f508a..cb6712b58ee 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java -@@ -173,7 +173,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException - } catch (InterruptedException x) {} - } - if (lastException != null) { -- throw new DebuggerException(lastException.getMessage(), lastException); -+ throw new DebuggerException(lastException); - } else { - return task; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -index 3fe795d34bc..52307b9cdcf 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2002, 2018, 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 -@@ -73,12 +73,8 @@ public String toString() { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); - ThreadContext context = LinuxThreadContextFactory.createThreadContext(debugger); -- // null means we failed to get the register set for some reason. The caller -- // is responsible for dealing with the set of null registers in that case. -- if (data != null) { -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -- } -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); - } - return context; - } -diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -index 377650a0a1c..ec5aea35e8c 100644 ---- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -30,9 +30,9 @@ - - class WindbgAMD64Thread implements ThreadProxy { - private WindbgDebugger debugger; -- private long sysId; // SystemID for Windows thread, stored in OSThread::_thread_id -+ private long sysId; - private boolean gotID; -- private long id; // ThreadID for Windows thread, returned by GetThreadIdBySystemId -+ private long id; - - // The address argument must be the address of the OSThread::_thread_id - WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { -@@ -50,12 +50,8 @@ class WindbgAMD64Thread implements ThreadProxy { - public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(getThreadID()); - WindbgAMD64ThreadContext context = new WindbgAMD64ThreadContext(debugger); -- // null means we failed to get the register set for some reason. The caller -- // is responsible for dealing with the set of null registers in that case. -- if (data != null) { -- for (int i = 0; i < data.length; i++) { -- context.setRegister(i, data[i]); -- } -+ for (int i = 0; i < data.length; i++) { -+ context.setRegister(i, data[i]); - } - return context; - } -@@ -90,7 +86,6 @@ public String toString() { - private long getThreadID() { - if (!gotID) { - id = debugger.getThreadIdFromSysId(sysId); -- gotID = true; - } - - return id; -diff --git a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -index e3b218b4dae..314cf69c957 100644 ---- a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -+++ b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp -@@ -45,7 +45,6 @@ - - #include - #include --#include - - #define DEBUG_NO_IMPLEMENTATION - #include -@@ -766,16 +765,9 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal - CHECK_EXCEPTION_(0); - - ULONG id = 0; -- HRESULT hr = ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id); -- if (hr != S_OK) { -- // This is not considered fatal and does happen on occassion, usually with an -- // 0x80004002 "No such interface supported". The root cause is not fully understood, -- // but by ignoring this error and returning NULL, stacking walking code will get -- // null registers and fallback to using the "last java frame" if setup. -- printf("WARNING: GetThreadIdBySystemId failed with 0x%x for sysId (%" PRIu64 ")\n", -- hr, sysId); -- return -1; -- } -+ COM_VERIFY_OK_(ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id), -+ "Windbg Error: GetThreadIdBySystemId failed!", 0); -+ - return (jlong) id; - } - - -From 4b01e13731fc330ca3d57a5cd532c91bc66579c8 Mon Sep 17 00:00:00 2001 -From: Kuai Wei -Date: Wed, 31 Jan 2024 17:26:31 +0800 -Subject: [PATCH 140/140] Remove unused zSyscall_linux_riscv.hpp - ---- - .../linux_riscv/gc/z/zSyscall_linux_riscv.hpp | 42 ------------------- - 1 file changed, 42 deletions(-) - delete mode 100644 src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp - -diff --git a/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp b/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp -deleted file mode 100644 -index 1aa58f27871..00000000000 ---- a/src/hotspot/os_cpu/linux_riscv/gc/z/zSyscall_linux_riscv.hpp -+++ /dev/null -@@ -1,42 +0,0 @@ --/* -- * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. -- * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. -- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -- * -- * This code is free software; you can redistribute it and/or modify it -- * under the terms of the GNU General Public License version 2 only, as -- * published by the Free Software Foundation. -- * -- * This code is distributed in the hope that it will be useful, but WITHOUT -- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -- * version 2 for more details (a copy is included in the LICENSE file that -- * accompanied this code). -- * -- * You should have received a copy of the GNU General Public License version -- * 2 along with this work; if not, write to the Free Software Foundation, -- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -- * -- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -- * or visit www.oracle.com if you need additional information or have any -- * questions. -- * -- */ -- --#ifndef OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP --#define OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP -- --#include -- --// --// Support for building on older Linux systems --// -- --#ifndef SYS_memfd_create --#define SYS_memfd_create 279 --#endif --#ifndef SYS_fallocate --#define SYS_fallocate 47 --#endif -- --#endif // OS_CPU_LINUX_RISCV_GC_Z_ZSYSCALL_LINUX_RISCV_HPP diff --git a/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch b/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch index 8d4548a..fc0fb34 100755 --- a/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch +++ b/G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch @@ -367,4 +367,4 @@ index 000000000..85b49171c --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ -+11.0.24.0.13 ++11.0.25.0.13 diff --git a/LoongArch64-support.patch b/LoongArch64-support.patch index bf78938..8446b94 100644 --- a/LoongArch64-support.patch +++ b/LoongArch64-support.patch @@ -18679,10 +18679,10 @@ index 0000000000..80dff0c762 + diff --git a/src/hotspot/cpu/loongarch/loongarch_64.ad b/src/hotspot/cpu/loongarch/loongarch_64.ad new file mode 100644 -index 0000000000..cc3824a402 +index 0000000000..c10f0b70cf --- /dev/null +++ b/src/hotspot/cpu/loongarch/loongarch_64.ad -@@ -0,0 +1,13917 @@ +@@ -0,0 +1,13928 @@ +// +// Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2015, 2023, Loongson Technology. All rights reserved. @@ -25123,6 +25123,17 @@ index 0000000000..cc3824a402 + ins_pipe(empty); +%} + ++instruct same_addr_load_fence() %{ ++ match(SameAddrLoadFence); ++ ins_cost(400); ++ ++ format %{ "MEMBAR @ same_addr_load_fence" %} ++ ins_encode %{ ++ __ dbar(0x700); ++ %} ++ ins_pipe(pipe_slow); ++%} ++ +//----------Move Instructions-------------------------------------------------- +instruct castX2P(mRegP dst, mRegL src) %{ + match(Set dst (CastX2P src)); @@ -38046,13 +38057,13 @@ index 0000000000..49302590c3 +#endif // CPU_LOONGARCH_MACROASSEMBLER_LOONGARCH_INLINE_HPP diff --git a/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp new file mode 100644 -index 0000000000..3ed4c36651 +index 0000000000..6e27a69747 --- /dev/null +++ b/src/hotspot/cpu/loongarch/macroAssembler_loongarch_trig.cpp -@@ -0,0 +1,1625 @@ +@@ -0,0 +1,1626 @@ +/* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Cavium. All rights reserved. (By BELLSOFT) -+ * Copyright (c) 2022, Loongson Technology. All rights reserved. ++ * Copyright (c) 2022, 2024, Loongson Technology. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it @@ -38951,7 +38962,7 @@ index 0000000000..3ed4c36651 + b(Q_DONE); + bind(JX_IS_0); + if (UseLASX) { -+ xvfmul_d(v28, v18, v6); // f[0,1] * x[0] ++ xvfmul_d(v28, v18, v6); // f[0,3] * x[0] + fmul_d(v30, v19, v6); // f[4] * x[0] + } else { + vfmul_d(v28, v18, v6); // f[0,1] * x[0] @@ -39180,6 +39191,7 @@ index 0000000000..3ed4c36651 + st_w(tmp2, SCR2, 0); + addi_w(SCR1, SCR1, 24); + addi_w(jz, jz, 1); ++ alsl_d(SCR2, jz, iqBase, 2 - 1); + st_w(tmp3, SCR2, 0); // iq[jz] = (int) fw + b(Z_ZERO_CHECK_DONE); + bind(Z_IS_LESS_THAN_TWO24B); @@ -104792,7 +104804,7 @@ index 3687754e71..791e4ed43f 100644 void generate_c1_load_barrier_stub(LIR_Assembler* ce, ZLoadBarrierStubC1* stub) const; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp -index 0af357ea56..66a8006780 100644 +index 2842a11f92..4f58ec4be3 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -23,6 +23,12 @@ @@ -104808,7 +104820,7 @@ index 0af357ea56..66a8006780 100644 // no precompiled headers #include "jvm.h" #include "classfile/classLoader.hpp" -@@ -4068,6 +4074,8 @@ size_t os::Linux::find_large_page_size() { +@@ -4060,6 +4066,8 @@ size_t os::Linux::find_large_page_size() { IA64_ONLY(256 * M) PPC_ONLY(4 * M) S390_ONLY(1 * M) @@ -108482,6 +108494,31 @@ index 2b0fa83c1a..270e0bc180 100644 +const bool ZPlatformLoadBarrierTestResultInRegister = false; + #endif // OS_CPU_LINUX_X86_ZGLOBALS_LINUX_X86_HPP +diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp +index f810fde767..90f733cdf9 100644 +--- a/src/hotspot/share/adlc/formssel.cpp ++++ b/src/hotspot/share/adlc/formssel.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. ++ */ ++ + // FORMS.CPP - Definitions for ADL Parser Forms Classes + #include "adlc.hpp" + +@@ -4109,6 +4115,7 @@ bool MatchRule::is_ideal_membar() const { + !strcmp(_opType,"MemBarVolatile") || + !strcmp(_opType,"MemBarCPUOrder") || + !strcmp(_opType,"MemBarStoreStore") || ++ !strcmp(_opType,"SameAddrLoadFence" ) || + !strcmp(_opType,"OnSpinWait"); + } + diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 4912f88056..a420f7807b 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp @@ -109872,6 +109909,46 @@ index 84815adea8..57e29f1295 100644 __ move(dirty, card_addr); __ branch_destination(L_already_dirty->label()); } else { +diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +index 5452756444..62adf9971e 100644 +--- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp ++++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.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 "gc/shared/c2/barrierSetC2.hpp" + #include "opto/arraycopynode.hpp" +@@ -197,6 +203,8 @@ public: + + bool is_volatile = (decorators & MO_SEQ_CST) != 0; + bool is_acquire = (decorators & MO_ACQUIRE) != 0; ++ bool is_relaxed = (decorators & MO_RELAXED) != 0; ++ bool is_unsafe = (decorators & C2_UNSAFE_ACCESS) != 0; + + // If reference is volatile, prevent following volatiles ops from + // floating up before the volatile access. +@@ -227,6 +235,13 @@ public: + assert(_leading_membar == NULL || 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(); ++ } else if (is_relaxed && is_unsafe) { ++#ifdef LOONGARCH64 ++ assert(kit != NULL, "unsupported at optimization time"); ++ Node* n = _access.raw_access(); ++ Node* mb = kit->insert_mem_bar(Op_SameAddrLoadFence, n); ++ mb->as_MemBar()->set_trailing_load(); ++#endif + } + } + } diff --git a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp b/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp index f51d186484..506f0301fe 100644 --- a/src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp @@ -110179,6 +110256,56 @@ index 6c631f5458..9865106720 100644 } // Note that the forwardee is not the same thing as the displaced_mark. +diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp +index 7a9bd91117..b46e9bcf5b 100644 +--- a/src/hotspot/share/opto/classes.hpp ++++ b/src/hotspot/share/opto/classes.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "utilities/macros.hpp" + + // The giant table of Node classes. +@@ -217,6 +223,7 @@ macro(StoreFence) + macro(MemBarReleaseLock) + macro(MemBarVolatile) + macro(MemBarStoreStore) ++macro(SameAddrLoadFence) + macro(MergeMem) + macro(MinD) + macro(MinF) +diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp +index da06b47400..510438d675 100644 +--- a/src/hotspot/share/opto/compile.cpp ++++ b/src/hotspot/share/opto/compile.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "asm/macroAssembler.hpp" + #include "asm/macroAssembler.inline.hpp" +@@ -3448,6 +3454,7 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { + n->set_req(MemBarNode::Precedent, top()); + } + break; ++ case Op_SameAddrLoadFence: + case Op_MemBarAcquire: { + if (n->as_MemBar()->trailing_load() && n->req() > MemBarNode::Precedent) { + // At parse time, the trailing MemBarAcquire for a volatile load diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 569fbc6d69..c1f1b82ffa 100644 --- a/src/hotspot/share/opto/compile.hpp @@ -110192,6 +110319,63 @@ index 569fbc6d69..c1f1b82ffa 100644 MAX_inst_size = 2048, #else MAX_inst_size = 1024, +diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp +index e194386b56..d5e6dd71a7 100644 +--- a/src/hotspot/share/opto/memnode.cpp ++++ b/src/hotspot/share/opto/memnode.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/systemDictionary.hpp" + #include "compiler/compileLog.hpp" +@@ -3190,6 +3196,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); ++ case Op_SameAddrLoadFence: return new SameAddrLoadFenceNode(C, atp, pn); + case Op_OnSpinWait: return new OnSpinWaitNode(C, atp, pn); + case Op_Initialize: return new InitializeNode(C, atp, pn); + case Op_MemBarStoreStore: return new MemBarStoreStoreNode(C, atp, pn); +diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp +index e4676977e1..bf1efbf835 100644 +--- a/src/hotspot/share/opto/memnode.hpp ++++ b/src/hotspot/share/opto/memnode.hpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #ifndef SHARE_VM_OPTO_MEMNODE_HPP + #define SHARE_VM_OPTO_MEMNODE_HPP + +@@ -1293,6 +1299,14 @@ public: + virtual uint ideal_reg() const { return 0; } // not matched in the AD file + }; + ++// Used to prevent LoadLoad reorder for same address. ++class SameAddrLoadFenceNode: public MemBarNode { ++public: ++ SameAddrLoadFenceNode(Compile* C, int alias_idx, Node* precedent) ++ : MemBarNode(C, alias_idx, precedent) {} ++ virtual int Opcode() const; ++}; ++ + class OnSpinWaitNode: public MemBarNode { + 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 b6540e06a3..52d1fc9fb9 100644 --- a/src/hotspot/share/opto/output.cpp @@ -110338,7 +110522,7 @@ index ce23aafa8f..d3dfb74d5b 100644 assert(_owner != Self, "invariant"); assert(_Responsible != Self, "invariant"); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp -index e0f4a2af1f..09cc4b1ba5 100644 +index 1c540bb621..0e44240d40 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -22,6 +22,12 @@ @@ -110397,6 +110581,31 @@ index e086f794cd..f480195775 100644 static const double S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp +index adce6da6a3..db099a2985 100644 +--- a/src/hotspot/share/runtime/vmStructs.cpp ++++ b/src/hotspot/share/runtime/vmStructs.cpp +@@ -22,6 +22,12 @@ + * + */ + ++/* ++ * This file has been modified by Loongson Technology in 2023, These ++ * modifications are Copyright (c) 2023, Loongson Technology, and are made ++ * available on the same license terms set forth above. ++ */ ++ + #include "precompiled.hpp" + #include "ci/ciField.hpp" + #include "ci/ciInstance.hpp" +@@ -1642,6 +1648,7 @@ typedef PaddedEnd PaddedObjectMonitor; + declare_c2_type(StoreFenceNode, MemBarNode) \ + declare_c2_type(MemBarVolatileNode, MemBarNode) \ + declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ ++ declare_c2_type(SameAddrLoadFenceNode, MemBarNode) \ + declare_c2_type(OnSpinWaitNode, MemBarNode) \ + declare_c2_type(InitializeNode, MemBarNode) \ + declare_c2_type(ThreadLocalNode, Node) \ diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index c758fc5743..a8c4638f6a 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp @@ -110672,7 +110881,7 @@ index 8318e8e021..07064e76ee 100644 // This C bool type must be int for compatibility with Linux calls and // it would be a mistake to equivalence it to C++ bool on many platforms diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c -index de5254d859..eefe55959c 100644 +index c22b5d1cb3..36d6343960 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c @@ -22,6 +22,12 @@ @@ -110688,12 +110897,12 @@ index de5254d859..eefe55959c 100644 #include #include #include -@@ -142,7 +148,7 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use - #define PTRACE_GETREGS_REQ PT_GETREGS - #endif - --#ifdef PTRACE_GETREGS_REQ -+#if defined(PTRACE_GETREGS_REQ) && !defined(loongarch64) +@@ -151,7 +157,7 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use + return false; + } + return true; +-#elif defined(PTRACE_GETREGS_REQ) ++#elif defined(PTRACE_GETREGS_REQ) && !defined(loongarch64) if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid); return false; @@ -116585,7 +116794,7 @@ index 127bb6abcd..c9277604ae 100644 Platform.isSolaris(); } diff --git a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java -index 77458554b7..05aee6b84c 100644 +index 126a43a900..55bd135f6e 100644 --- a/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +++ b/test/hotspot/jtreg/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java @@ -45,7 +45,7 @@ import java.util.Set; @@ -116625,35 +116834,8 @@ index 7990c49a1f..025048c6b0 100644 } } } -diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java -index b14daf6c6d..da33514c75 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.BufferedReader; -@@ -747,6 +753,9 @@ 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-mips64el-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/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java -index 5b3f1889cb..aaf8867a7c 100644 +index 6269373c2b..440ec4664f 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -21,6 +21,12 @@ @@ -116668,8 +116850,8 @@ index 5b3f1889cb..aaf8867a7c 100644 + package jdk.test.lib; - import java.io.FileNotFoundException; -@@ -226,6 +232,14 @@ public class Platform { + import java.io.BufferedReader; +@@ -229,6 +235,14 @@ public class Platform { return isArch("(i386)|(x86(?!_64))"); } diff --git a/change-ActivePrcoessorCount-only-for-HBase.patch b/change-ActivePrcoessorCount-only-for-HBase.patch new file mode 100644 index 0000000..3d604e5 --- /dev/null +++ b/change-ActivePrcoessorCount-only-for-HBase.patch @@ -0,0 +1,232 @@ +diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +index faf109ab1..ab83d2a6b 100644 +--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp ++++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +@@ -121,7 +121,8 @@ public: + static int get_initial_sve_vector_length() { return _initial_sve_vector_length; }; + + static bool is_hisi_enabled() { +- if (_cpu == CPU_HISILICON && (_model == 0xd01 || _model == 0xd02 || _model == 0xd03)) { ++ if (_cpu == CPU_HISILICON && (_model == 0xd01 || _model == 0xd02 || _model == 0xd03 || ++ _model == 0xd22 || _model == 0xd45)) { + return true; + } + return false; +diff --git a/make/hotspot/symbols/symbols-shared b/make/hotspot/symbols/symbols-shared +index 5d26d1028..d955c25f2 100644 +--- a/make/hotspot/symbols/symbols-shared ++++ b/make/hotspot/symbols/symbols-shared +@@ -28,6 +28,7 @@ jio_snprintf + jio_vfprintf + jio_vsnprintf + JNI_CreateJavaVM ++JNI_SetCParam + JNI_GetCreatedJavaVMs + JNI_GetDefaultJavaVMInitArgs + JVM_FindClassFromBootLoader +diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +index 9c2bdbbad..552267b0f 100644 +--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp ++++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +@@ -413,3 +413,28 @@ void VM_Version::initialize() { + + UNSUPPORTED_OPTION(CriticalJNINatives); + } ++ ++int VM_Version::get_cpu_model() { ++ int cpu_lines = 0; ++ if (FILE *f = fopen("/proc/cpuinfo", "r")) { ++ char buf[128], *p; ++ while (fgets(buf, sizeof (buf), f) != NULL) { ++ if ((p = strchr(buf, ':')) != NULL) { ++ long v = strtol(p+1, NULL, 0); ++ if (strncmp(buf, "CPU implementer", sizeof "CPU implementer" - 1) == 0) { ++ _cpu = v; ++ cpu_lines++; ++ } else if (strncmp(buf, "CPU variant", sizeof "CPU variant" - 1) == 0) { ++ _variant = v; ++ } else if (strncmp(buf, "CPU part", sizeof "CPU part" - 1) == 0) { ++ if (_model != v) _model2 = _model; ++ _model = v; ++ } else if (strncmp(buf, "CPU revision", sizeof "CPU revision" - 1) == 0) { ++ _revision = v; ++ } ++ } ++ } ++ fclose(f); ++ } ++ return cpu_lines; ++} +\ No newline at end of file +diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +index f03da8710..faf109ab1 100644 +--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp ++++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +@@ -112,6 +112,7 @@ public: + CPU_DMB_ATOMICS = (1 << 31), + }; + ++ static int get_cpu_model(); + static int cpu_family() { return _cpu; } + static int cpu_model() { return _model; } + static int cpu_model2() { return _model2; } +diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp +index 9084daeaa..0d7e03cd8 100644 +--- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp ++++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.cpp +@@ -46,6 +46,35 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, + return pd_get_top_frame(fr_addr, ucontext, isInJava); + } + ++inline unsigned int stringHash(const char* str) { ++ unsigned int seed = 13; ++ unsigned int hash = 0; ++ while(*str) { ++ hash = hash * seed + (*str++); ++ } ++ ++ return (hash & 0x7fffffff); ++} ++ ++void JavaThread::os_linux_aarch64_options(int apc, char **name) { ++ if (name == NULL) { ++ return; ++ } ++ VM_Version::get_cpu_model(); ++ if (VM_Version::is_hisi_enabled()) { ++ int i = 0; ++ int step = 0; ++ while (name[i] != NULL) { ++ if (stringHash(name[i]) == 1396789436) { ++ if (FLAG_IS_DEFAULT(ActiveProcessorCount) && (UseG1GC || UseParallelGC || UseZGC) && apc > 8) ++ FLAG_SET_DEFAULT(ActiveProcessorCount, 8); ++ break; ++ } ++ i++; ++ } ++ } ++} ++ + bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { + assert(this->is_Java_thread(), "must be JavaThread"); + JavaThread* jt = (JavaThread *)this; +diff --git a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp +index 985b664aa..521ac0dcc 100644 +--- a/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp ++++ b/src/hotspot/os_cpu/linux_aarch64/thread_linux_aarch64.hpp +@@ -55,6 +55,8 @@ + bool pd_get_top_frame_for_signal_handler(frame* fr_addr, void* ucontext, + bool isInJava); + ++ static void os_linux_aarch64_options(int apc, char **name); ++ + bool pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, bool isInJava); + private: + bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava); +diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp +index 289283dca..0b2138d98 100644 +--- a/src/hotspot/share/prims/jni.cpp ++++ b/src/hotspot/share/prims/jni.cpp +@@ -3951,6 +3951,11 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { + DT_RETURN_MARK_DECL(CreateJavaVM, jint + , HOTSPOT_JNI_CREATEJAVAVM_RETURN(_ret_ref)); + ++const char** argv_for_execvp; ++_JNI_IMPORT_OR_EXPORT_ void JNICALL JNI_SetCParam(char** raw_argv) { ++ argv_for_execvp = (const char**)raw_argv; ++} ++ + static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { + HOTSPOT_JNI_CREATEJAVAVM_ENTRY((void **) vm, penv, args); + +diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp +index 1c540bb62..214bb21f9 100644 +--- a/src/hotspot/share/runtime/os.cpp ++++ b/src/hotspot/share/runtime/os.cpp +@@ -447,6 +447,11 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { + } + + void os::init_before_ergo() { ++#ifdef AARCH64 ++ // global variables ++ extern char** argv_for_execvp; ++ JavaThread::os_linux_aarch64_options(active_processor_count(), argv_for_execvp); ++#endif + initialize_initial_active_processor_count(); + // We need to initialize large page support here because ergonomics takes some + // decisions depending on large page support and the calculated large page size. +diff --git a/src/java.base/share/native/include/jni.h b/src/java.base/share/native/include/jni.h +index e15503f4d..4aaa75685 100644 +--- a/src/java.base/share/native/include/jni.h ++++ b/src/java.base/share/native/include/jni.h +@@ -1948,6 +1948,9 @@ JNI_GetDefaultJavaVMInitArgs(void *args); + _JNI_IMPORT_OR_EXPORT_ jint JNICALL + JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args); + ++_JNI_IMPORT_OR_EXPORT_ void JNICALL ++JNI_SetCParam(char** raw_argv); ++ + _JNI_IMPORT_OR_EXPORT_ jint JNICALL + JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *); + +diff --git a/src/java.base/share/native/libjli/java.c b/src/java.base/share/native/libjli/java.c +index a38ddae63..120d8f33b 100644 +--- a/src/java.base/share/native/libjli/java.c ++++ b/src/java.base/share/native/libjli/java.c +@@ -284,6 +284,7 @@ JLI_Launch(int argc, char ** argv, /* main argc, argv */ + + ifn.CreateJavaVM = 0; + ifn.GetDefaultJavaVMInitArgs = 0; ++ ifn.raw_argv = argv; + + if (JLI_IsTraceLauncher()) { + start = CounterGet(); +@@ -1524,6 +1525,7 @@ InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn) + i, args.options[i].optionString); + } + ++ ifn->SetCParam(ifn->raw_argv); + r = ifn->CreateJavaVM(pvm, (void **)penv, &args); + JLI_MemFree(options); + return r == JNI_OK; +diff --git a/src/java.base/share/native/libjli/java.h b/src/java.base/share/native/libjli/java.h +index 45acece27..43ca5cf39 100644 +--- a/src/java.base/share/native/libjli/java.h ++++ b/src/java.base/share/native/libjli/java.h +@@ -77,13 +77,16 @@ + * Pointers to the needed JNI invocation API, initialized by LoadJavaVM. + */ + typedef jint (JNICALL *CreateJavaVM_t)(JavaVM **pvm, void **env, void *args); ++typedef void (JNICALL *SetCParam_t)(char** raw_argv); + typedef jint (JNICALL *GetDefaultJavaVMInitArgs_t)(void *args); + typedef jint (JNICALL *GetCreatedJavaVMs_t)(JavaVM **vmBuf, jsize bufLen, jsize *nVMs); + + typedef struct { + CreateJavaVM_t CreateJavaVM; ++ SetCParam_t SetCParam; + GetDefaultJavaVMInitArgs_t GetDefaultJavaVMInitArgs; + GetCreatedJavaVMs_t GetCreatedJavaVMs; ++ char** raw_argv; + } InvocationFunctions; + + JNIEXPORT int JNICALL +diff --git a/src/java.base/unix/native/libjli/java_md_solinux.c b/src/java.base/unix/native/libjli/java_md_solinux.c +index 160f91975..7526c0d9f 100644 +--- a/src/java.base/unix/native/libjli/java_md_solinux.c ++++ b/src/java.base/unix/native/libjli/java_md_solinux.c +@@ -615,6 +615,13 @@ LoadJavaVM(const char *jvmpath, InvocationFunctions *ifn) + return JNI_FALSE; + } + ++ ifn->SetCParam = (SetCParam_t) ++ dlsym(libjvm, "JNI_SetCParam"); ++ if (ifn->SetCParam == NULL) { ++ JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); ++ return JNI_FALSE; ++ } ++ + ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) + dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); + if (ifn->GetDefaultJavaVMInitArgs == NULL) { +-- +2.21.0.windows.1 diff --git a/delete_expired_certificates.patch b/delete_expired_certificates.patch index 3e654b7..19a0e15 100644 --- a/delete_expired_certificates.patch +++ b/delete_expired_certificates.patch @@ -120,19 +120,18 @@ index 122a01901..c131bd493 100644 + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. -- private static final int COUNT = 110; -+ private static final int COUNT = 107; +- private static final int COUNT = 112; ++ private static final int COUNT = 109; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM -- = "C1:68:B4:AC:51:BF:B5:C6:FD:20:69:17:E1:AF:E4:5B:01:9B:AA:3F:C3:9A:80:A8:51:53:74:2C:A2:04:B0:FF"; -+ = "D5:F6:74:0F:13:CF:6D:35:5E:10:04:C3:1B:57:C4:F4:A0:49:9A:26:38:89:53:C3:71:10:60:9D:48:20:E7:DE"; +- = "8F:E0:6F:7F:21:59:33:A6:43:F3:48:FD:A3:4A:8E:28:35:AA:DD:6E:A5:43:56:F1:28:34:48:DF:5C:D2:7C:72"; ++ = "20:83:CF:5E:F7:A9:E6:C6:06:ED:2C:28:3E:CE:AF:B9:BF:9D:26:CB:29:0C:E2:CF:B8:4F:DF:E9:59:5F:A6:3C"; // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") - private static final Map FINGERPRINT_MAP = new HashMap<>() { -@@ -109,8 +109,6 @@ public class VerifyCACerts { +@@ -110,8 +110,6 @@ public class VerifyCACerts { "7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2"); put("digicerthighassuranceevrootca [jdk]", "74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF"); @@ -141,7 +140,7 @@ index 122a01901..c131bd493 100644 put("geotrustprimaryca [jdk]", "37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C"); put("geotrustprimarycag2 [jdk]", -@@ -145,10 +143,6 @@ public class VerifyCACerts { +@@ -146,10 +144,6 @@ public class VerifyCACerts { "96:BC:EC:06:26:49:76:F3:74:60:77:9A:CF:28:C5:A7:CF:E8:A3:C0:AA:E1:1A:8F:FC:EE:05:C0:BD:DF:08:C6"); put("letsencryptisrgx2 [jdk]", "69:72:9B:8E:15:A8:6E:FC:17:7A:57:AF:B7:17:1D:FC:64:AD:D2:8C:2F:CA:8C:F1:50:7E:34:45:3C:CB:14:70"); @@ -152,7 +151,7 @@ index 122a01901..c131bd493 100644 put("quovadisrootca1g3 [jdk]", "8A:86:6F:D1:B2:76:B5:7E:57:8E:92:1C:65:82:8A:2B:ED:58:E9:F2:F2:88:05:41:34:B7:F1:F4:BF:C9:CC:74"); put("quovadisrootca2 [jdk]", -@@ -282,12 +276,6 @@ public class VerifyCACerts { +@@ -291,12 +285,6 @@ public class VerifyCACerts { add("addtrustexternalca [jdk]"); // Valid until: Sat May 30 10:44:50 GMT 2020 add("addtrustqualifiedca [jdk]"); diff --git a/jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz b/jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz deleted file mode 100644 index 360f3a8..0000000 Binary files a/jdk-updates-jdk11u-jdk-11.0.19-ga.tar.gz and /dev/null differ diff --git a/jdk-updates-jdk11u-jdk-11.0.24-ga.tar.xz b/jdk-updates-jdk11u-jdk-11.0.25-ga.tar.xz similarity index 82% rename from jdk-updates-jdk11u-jdk-11.0.24-ga.tar.xz rename to jdk-updates-jdk11u-jdk-11.0.25-ga.tar.xz index c3b6809..0a86b9f 100644 Binary files a/jdk-updates-jdk11u-jdk-11.0.24-ga.tar.xz and b/jdk-updates-jdk11u-jdk-11.0.25-ga.tar.xz differ diff --git a/openjdk-11.spec b/openjdk-11.spec index e981b12..4bbba21 100644 --- a/openjdk-11.spec +++ b/openjdk-11.spec @@ -22,6 +22,9 @@ # Enable release builds by default on relevant arches. %bcond_without release +# Disable global LTO +%define _lto_cflags %{nil} + # The -g flag says to use strip -g instead of full strip on DSOs or EXEs. # This fixes detailed NMT and other tools which need minimal debug info. # See: https://bugzilla.redhat.com/show_bug.cgi?id=1520879 @@ -125,14 +128,14 @@ # New Version-String scheme-style defines %global majorver 11 -%global securityver 24 +%global securityver 25 # 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 %{majorver} %ifnarch loongarch64 ppc64le -%global vendor_version_string Bisheng +%global vendor_version_string BiSheng %endif %ifarch loongarch64 %global vendor_version_string Loongson @@ -146,12 +149,12 @@ %global origin_nice OpenJDK %global top_level_dir_name %{origin} %global minorver 0 -%global buildver 8 +%global buildver 9 %global patchver 0 %global project jdk-updates %global repo jdk11u -%global revision jdk-11.0.24-ga +%global revision jdk-11.0.25-ga %global full_revision %{project}-%{repo}-%{revision} # priority must be 7 digits in total # setting to 1, so debug ones can have 0 @@ -695,6 +698,9 @@ Provides: java-%{origin}-headless%{?1} = %{epoch}:%{version}-%{release} Provides: jre-%{origin}-headless%{?1} = %{epoch}:%{version}-%{release} Provides: java-headless%{?1} = %{epoch}:%{version}-%{release} Provides: jre-headless%{?1} = %{epoch}:%{version}-%{release} + +# To fix /usr/bin/jjs not provided +Provides: /usr/bin/jjs } %define java_devel_rpo() %{expand: @@ -762,7 +768,7 @@ Provides: java-src%{?1} = %{epoch}:%{version}-%{release} Name: java-%{javaver}-%{origin} Version: %{newjavaver}.%{buildver} -Release: 0 +Release: 3 # 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 # also included the epoch in their virtual provides. This created a @@ -791,7 +797,7 @@ Group: Development/Languages # 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/ @@ -808,15 +814,6 @@ Source9: jconsole.desktop.in # nss configuration file Source11: nss.cfg.in -############################################ -# -# RPM/distribution specific patches -# -############################################ -# NSS via SunPKCS11 Provider (disabled comment -# due to memory leak). -Patch1000: rh1648249-add_commented_out_nss_cfg_provider_to_java_security.patch - ############################################ # # LoongArch64 specific patches @@ -902,6 +899,9 @@ Patch92: 8295068-SSLEngine-throws-NPE-parsing-Certificate.patch # 11.0.23 Patch93: Cache-byte-when-constructing-String-with-duplicate-c.patch + +# 11.0.25 +Patch94: change-ActivePrcoessorCount-only-for-HBase.patch ############################################ # # riscv64 specific patches @@ -1194,6 +1194,7 @@ pushd %{top_level_dir_name} %patch91 -p1 %patch92 -p1 %patch93 -p1 +%patch94 -p1 %endif %endif %ifarch loongarch64 @@ -1201,8 +1202,6 @@ pushd %{top_level_dir_name} %endif popd # openjdk -# %patch1000 - # Extract systemtap tapsets %if %{with_systemtap} tar --strip-components=1 -x -I xz -f %{SOURCE8} @@ -1291,7 +1290,7 @@ bash ../configure \ --with-version-opt="" \ --with-vendor-version-string="%{vendor_version_string}" \ %ifnarch loongarch64 ppc64le - --with-vendor-name="Bisheng" \ + --with-vendor-name="BiSheng" \ %endif %ifarch loongarch64 --with-vendor-name="Loongson" \ @@ -1588,9 +1587,10 @@ else end end -- run content of included file with fake args +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" -arg = {"--currentjvm", "%{uniquesuffix %{nil}}", "--jvmdir", "%{_jvmdir %{nil}}", "--origname", "%{name}", "--origjavaver", "%{javaver}", "--arch", "%{_arch}", "--temp", "%{rpm_state_dir}/%{name}.%{_arch}"} -cjc.mainProgram(arg) +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}} @@ -1715,7 +1715,40 @@ cjc.mainProgram(arg) %changelog -* Thu July 18 2024 DXwangg - 1.11.0.24.8-0 +* Wed Nov 6 2024 Pan Xuefeng - 1:11.0.25.9-3 +- update LoongArch64 port to 11.0.25 + +* Wed Oct 23 2024 Dingli Zhang - 1:11.0.25.9-2 +- update riscv64 port to 11.0.25 + +* Mon Oct 21 2024 wuyafang - 1:11.0.25.9-1 +- disable lto in spec +- add Provides: /usr/bin/jjs +- update license + +* Wed Oct 16 2024 wuyafang - 1:11.0.25.9-0 +- upgrade to 11.0.25+9(GA) +- change default ActiveProcessorCount only for HBase + +* Fri Aug 30 2024 songliyang - 1.11.0.24.8-6 +- update License + +* Thu Aug 1 2024 aoqi - 1.11.0.24.8-5 +- update LoongArch64 port to 11.0.24 + +* Thu Jul 29 2024 DXwangg - 1.11.0.24.8-4 +- modified delete_expired_certificates.patch + +* Thu Jul 25 2024 songliyang - 1.11.0.24.8-3 +- update Loongarch support patch to fix the error while applying in prep stage + +* Tue Jul 23 2024 songliyang - 1.11.0.24.8-2 +- null the arg to solve openjdk-headless install error + +* Thu Jul 18 2024 Dingli Zhang - 1.11.0.24.8-1 +- update riscv64 port to 11.0.24 + +* Thu Jul 18 2024 DXwangg - 1.11.0.24.8-0 - update to 11.0.24+8(GA) * Thu Jun 20 2024 aoqi - 1.11.0.23.9-6 @@ -1739,7 +1772,7 @@ cjc.mainProgram(arg) * Thu Apr 18 2024 huangjie - 1:11.0.23.9-0 - modified 8224675-Late-GC-barrier-insertion-for-ZGC.patch -- modified delete_expired_certificates.patch +- modified delete_expired_certificates.patch * Wed Mar 13 2024 jiahua.yu - 1:11.0.22.7-3 - init support for arch ppc64le @@ -1750,9 +1783,6 @@ cjc.mainProgram(arg) * Tue Feb 20 2024 Leslie Zhai - 1:11.0.22.7-1 - init support of LoongArch64 -* Mon Mar 25 2024 neu-mobi - 1:11.0.22.7-1 -- add string optimization - * Wed Jan 17 2024 DXwangg - 1:11.0.22.7-0 - update to 11.0.22+7(GA) - modified delete_expired_certificates.patch @@ -1764,7 +1794,7 @@ cjc.mainProgram(arg) * Thu Oct 19 2023 DXwangg - 1:11.0.21.9-0 - update to 11.0.21+9(GA) - modified delete_expired_certificates.patch -- modified G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch +- modified G1-iterate-region-by-bitmap-rather-than-obj-size-in.patch - modified 8210473-JEP-345-NUMA-Aware-Memory-Allocation-for-G1.patch - modified 8214527-AArch64-ZGC-for-Aarch64.patch diff --git a/rh1648249-add_commented_out_nss_cfg_provider_to_java_security.patch b/rh1648249-add_commented_out_nss_cfg_provider_to_java_security.patch deleted file mode 100644 index 1b92ddc..0000000 --- a/rh1648249-add_commented_out_nss_cfg_provider_to_java_security.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -r 5b86f66575b7 src/share/lib/security/java.security-linux ---- openjdk/src/java.base/share/conf/security/java.security Tue May 16 13:29:05 2017 -0700 -+++ openjdk/src/java.base/share/conf/security/java.security Tue Jun 06 14:05:12 2017 +0200 -@@ -83,6 +83,7 @@ - #ifndef solaris - security.provider.tbd=SunPKCS11 - #endif -+#security.provider.tbd=SunPKCS11 ${java.home}/lib/security/nss.cfg - - # - # A list of preferred providers for specific algorithms. These providers will