diff --git a/Add-riscv64-support.patch b/Add-riscv64-support.patch index 59017ae..b06b0fe 100644 --- a/Add-riscv64-support.patch +++ b/Add-riscv64-support.patch @@ -1,346 +1,129 @@ -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..b1c333f711 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://httpredir.debian.org/debian/ ++ 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/.jcheck/conf b/.jcheck/conf +index be7ad6d26f..e35eb77696 100644 +--- a/.jcheck/conf ++++ b/.jcheck/conf +@@ -1,5 +1,5 @@ + [general] +-project=jdk-updates ++project=riscv-port + jbs=JDK + version=11.0.24 + +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 +136,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 +156,8 @@ 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/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 +167,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 +180,9 @@ 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 -@@ -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. - * 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) { - } - - --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"); -+ - 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) { - } - } - -+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"); - --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 +365,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..a83d43a8f1 --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp -@@ -0,0 +1,372 @@ +@@ -0,0 +1,365 @@ +/* + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -974,9 +653,9 @@ index 00000000000..f15ef5304c5 + } +#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; @@ -984,13 +663,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 +682,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 +736,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..9e7d271860 --- /dev/null +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp -@@ -0,0 +1,3047 @@ +@@ -0,0 +1,3057 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -1253,13 +925,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 +1019,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 @@ -1387,7 +1060,6 @@ index 00000000000..4923962a496 + 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); @@ -1966,7 +1638,6 @@ index 00000000000..4923962a496 + emit(insn); \ + } + -+ INSN(fence_i, 0b0001111, 0b001, 0b000000000000); + INSN(ecall, 0b1110011, 0b000, 0b000000000000); + INSN(_ebreak, 0b1110011, 0b000, 0b000000000001); + @@ -3014,6 +2685,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 +2760,7 @@ index 00000000000..4923962a496 + + INSN(rori, 0b0010011, 0b101, 0b011000); + INSN(slli_uw, 0b0011011, 0b001, 0b000010); ++ INSN(bexti, 0b0010011, 0b101, 0b010010); + +#undef INSN + @@ -4097,6 +3770,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 +3794,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,10 +3852,10 @@ 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..f60e0e38ae --- /dev/null +++ b/src/hotspot/cpu/riscv/bytes_riscv.hpp -@@ -0,0 +1,167 @@ +@@ -0,0 +1,165 @@ +/* + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. @@ -4203,8 +3885,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 @@ -4343,10 +4023,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..12980c12de --- /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 +4068,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 +4087,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 +4112,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 +4319,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]; @@ -4702,7 +4368,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 +4458,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 +4494,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 +4532,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 +4694,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 +4852,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 +4926,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 +5080,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 +5276,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 +5294,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 +5324,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 +5339,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 +5371,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 +5414,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..b7f53e395f --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp @@ -0,0 +1,388 @@ @@ -6138,7 +5808,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 +5866,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..1e482d7cc2 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp -@@ -0,0 +1,2267 @@ +@@ -0,0 +1,2268 @@ +/* + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -6243,7 +5913,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 +5962,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 +6226,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 +6279,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 +6289,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 +6533,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 +6655,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 +6700,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 +6735,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 +6781,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); +} @@ -7470,7 +7134,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()); @@ -7586,6 +7250,11 @@ 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"); @@ -7711,12 +7380,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 +7402,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(); @@ -8016,11 +7672,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 +7722,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 +7882,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 */); @@ -8469,10 +8140,10 @@ index 00000000000..742c2126e60 +#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..5c81f1c704 --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.hpp -@@ -0,0 +1,132 @@ +@@ -0,0 +1,133 @@ +/* + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -8548,6 +8219,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 +8279,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 +8323,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 +8490,7 @@ index 00000000000..e126f148cdf + break; + default: + ShouldNotReachHere(); ++ r = NULL; + } + return r; +} @@ -8890,6 +8562,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 +8575,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 +8645,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 +8672,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 +8683,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 +8757,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 +8936,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 +8964,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 +9354,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 +9379,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 +9412,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 +9440,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 +9479,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 +9568,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..99d981f97f --- /dev/null +++ b/src/hotspot/cpu/riscv/c1_MacroAssembler_riscv.cpp -@@ -0,0 +1,432 @@ +@@ -0,0 +1,443 @@ +/* + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -9916,8 +9607,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 +9624,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 +9636,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 @@ -9988,6 +9677,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())); ++ add_memory_int32(Address(t1, 0), 1); ++ } + return null_check_offset; +} + @@ -9997,13 +9690,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 +9731,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 +9891,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 +9909,7 @@ 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() { +} + +void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) { @@ -10315,10 +10017,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 +10082,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 +10144,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..329df2e1ca --- /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 +10196,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 +10316,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 +10341,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 +10354,7 @@ index 00000000000..f523c9ed50a + + +StubFrame::~StubFrame() { -+ if (_return_state == requires_return) { -+ __ epilogue(); -+ } else { -+ __ should_not_reach_here(); -+ } ++ __ epilogue(); + _sasm = NULL; +} + @@ -10825,6 +10517,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 +10565,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 +10623,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 +10730,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 +10829,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 +11114,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); + } @@ -11474,7 +11215,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 +11234,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 +11250,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 +11258,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 +11266,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 +11274,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 +11297,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 +11313,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 +11336,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,7 +11344,7 @@ index 00000000000..f523c9ed50a + + 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(); @@ -11619,10 +11360,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 +11398,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 +11410,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 +11421,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 +11476,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 +11522,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 +11533,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 +11575,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 +11619,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 +11694,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 +11711,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 +11722,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 +11742,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 +11761,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 +11774,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 +11807,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 +11836,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 +11918,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 +11956,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 +11965,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 +11982,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 +12013,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 +12082,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 +12098,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 +12134,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 +12196,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 +12205,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 +12288,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 +12406,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 +12432,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 +12482,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 +12525,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 +12599,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 +12621,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 +12758,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 +12823,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 +13062,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,15 +13073,14 @@ 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..e191cbcee2 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/g1/g1BarrierSetAssembler_riscv.cpp -@@ -0,0 +1,484 @@ +@@ -0,0 +1,481 @@ +/* + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved. @@ -15546,21 +13240,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); + @@ -15585,6 +13273,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 +13291,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 +13327,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); @@ -15727,7 +13417,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 +13498,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 +13517,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 +13564,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 +13648,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 +13685,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..2b556b95d7 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/barrierSetAssembler_riscv.cpp -@@ -0,0 +1,302 @@ +@@ -0,0 +1,231 @@ +/* + * 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 +13718,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" @@ -16230,82 +13920,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 +13956,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 +13998,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..81d47d61d4 --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/cardTableBarrierSetAssembler_riscv.cpp -@@ -0,0 +1,111 @@ +@@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. @@ -16611,7 +14051,11 @@ index 00000000000..a419f92b5f6 + 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,6 +14070,9 @@ index 00000000000..a419f92b5f6 + __ sb(zr, Address(tmp)); + __ bind(L_already_dirty); + } else { ++ if (ct->scanned_concurrently()) { ++ __ membar(MacroAssembler::StoreStore); ++ } + __ sb(zr, Address(tmp)); + } +} @@ -16636,6 +14083,10 @@ index 00000000000..a419f92b5f6 + 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 +14095,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); @@ -16681,7 +14135,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,7 +14183,7 @@ 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..7aa2015f9e --- /dev/null +++ b/src/hotspot/cpu/riscv/gc/shared/modRefBarrierSetAssembler_riscv.cpp @@ -0,0 +1,55 @@ @@ -16790,7 +14244,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 +14305,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 +14414,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 +14428,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..b8534c52e7 --- /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 +14461,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 +14478,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 +14552,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 +14652,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 +14690,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 +14709,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 +14761,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); @@ -17535,7 +14953,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 +14966,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 +14979,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 +15058,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 +15066,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 +15082,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 +15195,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 +15214,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 +15243,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 +15434,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 +15453,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 +15494,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 +15502,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 +15545,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 +15577,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 +15591,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 +15612,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 +15709,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 +15741,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 +15783,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 +15831,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..b50be7e726 --- /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 +15870,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 +16132,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,11 +16339,12 @@ 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); + } @@ -20059,7 +16395,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 +16415,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 +16606,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 +16620,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 @@ -20322,6 +16647,12 @@ index 00000000000..d12dcb2af19 + + // 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 +16683,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 +16705,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 +16721,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); + @@ -21327,7 +17666,7 @@ index 00000000000..d12dcb2af19 + 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); + } @@ -21429,10 +17768,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 +17896,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,7 +18057,7 @@ 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..776b078723 --- /dev/null +++ b/src/hotspot/cpu/riscv/interpreterRT_riscv.cpp @@ -0,0 +1,295 @@ @@ -22004,12 +18341,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 +18355,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 +18432,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 +18521,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 +18616,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 +18652,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 +18727,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 +18760,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 +18798,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 +18839,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..e18bd3d8e2 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp -@@ -0,0 +1,4016 @@ +@@ -0,0 +1,5410 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -22566,14 +18886,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 @@ -22716,6 +19037,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 @@ -22773,6 +19110,30 @@ index 00000000000..86710295444 + } +} + ++// 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 +19218,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 +19234,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. ++ mv(t0, (address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; @@ -22939,7 +19273,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. ++ mv(t0, (address)b); + + // call indirectly to solve generation ordering problem + int32_t offset = 0; @@ -23056,8 +19393,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 +19419,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 +19430,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) { @@ -23571,52 +19900,6 @@ index 00000000000..86710295444 + 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. @@ -23657,7 +19940,7 @@ index 00000000000..86710295444 + 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); @@ -23667,28 +19950,10 @@ index 00000000000..86710295444 + 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++) { @@ -23727,12 +19992,12 @@ 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; +} + @@ -23804,9 +20069,9 @@ 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; +} @@ -23884,7 +20149,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 +20162,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)); + } + } @@ -23913,7 +20178,7 @@ index 00000000000..86710295444 +} + +void MacroAssembler::mv(Register Rd, address addr) { -+ // Here in case of use with relocation, use fix length instruciton ++ // Here in case of use with relocation, use fix length instruction + // movptr instead of li + movptr(Rd, addr); +} @@ -23995,7 +20260,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 +20277,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 +20294,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 +20311,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 +20344,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 +20368,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 +20382,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 +20404,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; + } @@ -24181,8 +20446,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 +20458,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 +20470,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 +20516,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()); @@ -24293,22 +20554,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 +20595,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 +20608,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 +20649,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 +20665,10 @@ index 00000000000..86710295444 + } + + 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 { @@ -24440,9 +20685,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 +20695,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 +20707,10 @@ index 00000000000..86710295444 + } + + 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) { @@ -24483,22 +20728,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; @@ -24710,16 +20955,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); + } +} + @@ -25266,7 +21512,7 @@ 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); +} @@ -25304,7 +21550,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 +21585,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) { ++ code_section()->relocate(pc(), rtype); ++ lwu(zr, Address(dest, offset)); +} + +void MacroAssembler::set_narrow_oop(Register dst, jobject obj) { @@ -25366,7 +21834,7 @@ 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); @@ -25381,12 +21849,12 @@ 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); + li32(dst, nk); + zero_extend(dst, dst, 32); +} @@ -25409,7 +21877,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()); @@ -25527,17 +21995,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, @@ -26085,7 +22542,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); @@ -26177,7 +22634,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; + } @@ -26427,7 +22884,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 +22906,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 +22925,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 +22971,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 ++ 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(); + } +} -+#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..c660bce437 --- /dev/null +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp -@@ -0,0 +1,858 @@ +@@ -0,0 +1,966 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -26576,8 +24290,6 @@ index 00000000000..23e09475be1 + +#include "asm/assembler.hpp" +#include "metaprogramming/enableIf.hpp" -+#include "oops/compressedOops.hpp" -+#include "utilities/powerOfTwo.hpp" + +// MacroAssembler extends Assembler by frequently used macros. +// @@ -26591,10 +24303,34 @@ 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); @@ -26694,13 +24430,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 +24457,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 +24499,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 @@ -27031,12 +24761,6 @@ index 00000000000..23e09475be1 + 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 @@ -27054,8 +24778,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 +24791,17 @@ index 00000000000..23e09475be1 + } + + // mv -+ template::value)> -+ inline void mv(Register Rd, T o) { -+ li(Rd, (int64_t)o); -+ } ++ 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, address dest); + void mv(Register Rd, RegisterOrConstant src); + + // logic @@ -27178,8 +24904,13 @@ 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); @@ -27189,10 +24920,6 @@ index 00000000000..23e09475be1 + + 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); @@ -27330,9 +25057,6 @@ index 00000000000..23e09475be1 + 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 +25065,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 +25097,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 +25227,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 +25262,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..fd907f77af --- /dev/null +++ b/src/hotspot/cpu/riscv/methodHandles_riscv.cpp -@@ -0,0 +1,461 @@ +@@ -0,0 +1,450 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -27650,7 +25297,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" @@ -27673,10 +25319,10 @@ index 00000000000..1f7c0c87c21 +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 +25337,11 @@ 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; @@ -27763,13 +25409,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 @@ -27804,13 +25450,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) @@ -27903,24 +25542,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 +25680,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 +25720,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 +25762,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 +25783,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..27011ad128 --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp -@@ -0,0 +1,429 @@ +@@ -0,0 +1,417 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -28242,7 +25878,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 @@ -28299,8 +25935,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; @@ -28426,15 +26061,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 +26085,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; +} + @@ -28582,10 +26206,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..2e5c84ee3b --- /dev/null +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp -@@ -0,0 +1,572 @@ +@@ -0,0 +1,555 @@ +/* + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved. @@ -28629,7 +26253,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. @@ -28899,18 +26522,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 +26569,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 +26577,8 @@ index 00000000000..718b2e3de6c + } + } + -+ void verify(); -+ void print(); ++ void verify(); ++ void print(); + + // Creation + inline friend NativeMovConstReg* nativeMovConstReg_at(address addr); @@ -28969,55 +26588,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 +26665,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 +26764,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 +26806,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 +26813,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 +27045,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 +27052,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 +27083,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 +27136,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 +27155,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 +27182,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 +27227,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 +27246,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 +27275,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 +27314,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 +27329,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 +27392,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 +27517,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 +27588,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 +27638,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..02d6167629 --- /dev/null +++ b/src/hotspot/cpu/riscv/riscv.ad -@@ -0,0 +1,10611 @@ +@@ -0,0 +1,10280 @@ +// +// Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -30071,177 +27871,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 +27968,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 +28266,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 +28286,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 +28316,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 +28384,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 +28442,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 +28454,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 +28479,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 +28501,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 +28571,6 @@ index 00000000000..588887e1d96 + } +} + -+int MachCallNativeNode::ret_addr_offset() { -+ Unimplemented(); -+ return -1; -+} -+ +// +// Compute padding required for nodes which need alignment +// @@ -31062,6 +28599,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 +28623,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 +28641,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 +28655,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 +28684,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,27 +28694,16 @@ 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 @@ -31171,39 +28711,23 @@ index 00000000000..588887e1d96 + + 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 +28751,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 +28766,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 +28776,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 +28787,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 +28805,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 +28838,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 +28876,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 +28960,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 +28997,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 +29033,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,7 +29048,7 @@ 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); @@ -31588,7 +29075,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 +29093,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 +29119,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 +29176,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 +29202,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 +29335,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 +29381,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,7 +29427,7 @@ 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); @@ -31930,7 +29435,7 @@ index 00000000000..588887e1d96 + %} + + 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) { @@ -31949,19 +29454,30 @@ index 00000000000..588887e1d96 + %} + + 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); + %} + ++ 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 +29490,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 +29508,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 +29553,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 +29583,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) { @@ -32086,7 +29602,7 @@ index 00000000000..588887e1d96 + %} + + 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 +29634,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 +29644,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 +29652,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 +29680,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 +29695,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); ++ __ 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 ++ ++ 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 +29779,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 +29841,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 +29849,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 +29857,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 +29865,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 +29873,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 +29891,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 +29962,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 +29993,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 +30017,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 +30292,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 +30326,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 +30788,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 +30845,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 +30860,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 +30875,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 +31068,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 +31090,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 +31580,7 @@ index 00000000000..588887e1d96 + LDST : MEM; +%} + -+//------- Store pipeline operations ----------------------- ++//------- Control transfer pipeline operations ------------ + +// Store - zr, mem +// E.g. SD zr, mem @@ -34444,7 +31943,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 +32097,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 +32226,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 +32426,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 +32550,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 +32576,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 +32599,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 +32622,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 +32644,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 +32660,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 +32678,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 +32692,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 +32710,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 +32735,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 +32759,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 +32777,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 +32797,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 +32813,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 +32838,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 +32860,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 +32943,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 +32962,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 +32986,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 +33077,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 +33098,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))); + @@ -35607,7 +33122,7 @@ index 00000000000..588887e1d96 +%} + +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))); + @@ -35692,7 +33207,6 @@ 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); @@ -35712,7 +33226,7 @@ index 00000000000..588887e1d96 +%} + +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)); + @@ -35738,7 +33252,7 @@ index 00000000000..588887e1d96 +%} + +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)); + @@ -35831,7 +33345,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))); + @@ -35898,7 +33412,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 +33478,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 +34798,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 +35156,6 @@ index 00000000000..588887e1d96 + +instruct membar_storestore() %{ + match(MemBarStoreStore); -+ match(StoreStoreFence); + ins_cost(ALU_COST); + + format %{ "MEMBAR-store-store\t#@membar_storestore" %} @@ -37728,17 +35240,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 +35262,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 +35497,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 +36056,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 +36076,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 +36135,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 +36154,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 +36175,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 +36195,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 +36216,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 +36236,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 +36253,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 +36270,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 +36288,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 +36306,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 +36581,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 +36630,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 +36645,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 +36688,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 +36703,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 +36721,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 +36739,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 +36757,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 +36775,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 +36790,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 +36806,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 +36823,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 +36839,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 +37141,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 +37150,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 +37158,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 +37175,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 +37184,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 +37209,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 +37218,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 +37226,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 +37410,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 +37428,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 +37445,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 +37463,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 +37609,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 +37622,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 +37644,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 +37661,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 +37677,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 +37694,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 +37711,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 +37924,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 +37955,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 +37971,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 +37986,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 +38001,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 +38016,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 +38031,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 +38045,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 +38059,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 +38073,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 +38088,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 +38106,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 +38125,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 +38143,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 +38162,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 +38176,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 +38190,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 +38204,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 +38219,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 +38234,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 +38249,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 +38263,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 +38278,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 +38296,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 +38315,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 +38331,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 +38348,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 +38364,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 +38378,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..f41a496093 --- /dev/null +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp -@@ -0,0 +1,2761 @@ +@@ -0,0 +1,2666 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. @@ -43146,9 +38483,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 +38493,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 +38504,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,15 +38532,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 @@ -43227,9 +38542,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 +38557,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) { @@ -43273,18 +38581,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 +38636,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] = { @@ -43420,10 +38734,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(); @@ -43712,39 +39022,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, @@ -44133,10 +39414,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,7 +39489,8 @@ 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(); @@ -44368,27 +39650,14 @@ index 00000000000..f85d4b25a76 + // 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())); ++ __ 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 +39854,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 +39934,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 +39950,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 +39966,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 +40215,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 @@ -45262,14 +40520,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 +40739,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 +40796,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); @@ -45608,7 +40858,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 +40930,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 +41069,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..9970229c5c --- /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 +41120,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 +41193,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 +41239,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 +41298,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 +41357,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); @@ -46169,6 +41461,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); @@ -46379,16 +41684,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); @@ -46892,12 +42187,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 +42255,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); @@ -48206,50 +43491,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 +43927,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 @@ -49656,22 +44792,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 +44813,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 +44877,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 +44954,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 +45030,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 +45042,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..e639fa7e12 --- /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 +45099,6 @@ index 00000000000..6537b2dbd94 +#include "runtime/timer.hpp" +#include "runtime/vframeArray.hpp" +#include "utilities/debug.hpp" -+#include "utilities/powerOfTwo.hpp" +#include + +#ifndef PRODUCT @@ -50491,31 +45604,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 +45862,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 +45942,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 +46001,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 +46075,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 +46240,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 +46296,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 +46487,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 +46532,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); @@ -51728,10 +46881,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..84b1afc7dc --- /dev/null +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp -@@ -0,0 +1,3951 @@ +@@ -0,0 +1,4006 @@ +/* + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, Red Hat Inc. All rights reserved. @@ -51762,7 +46915,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 +46930,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) { @@ -52139,7 +47296,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 +48631,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 +48656,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 +48733,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 +49193,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 +49207,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 +49216,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 +50122,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 +50306,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 +50495,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 +50510,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); @@ -55685,7 +50893,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 +50939,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 +50987,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 +51182,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 +51239,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 +51249,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 +51259,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 +51268,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 +51289,10 @@ index 00000000000..768c7633ca6 +#ifdef COMPILER2 + c2_initialize(); +#endif // COMPILER2 ++ ++ UNSUPPORTED_OPTION(CriticalJNINatives); ++ ++ FLAG_SET_DEFAULT(UseMembar, true); +} + +#ifdef COMPILER2 @@ -56041,10 +51313,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 +51356,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 +51402,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 +51431,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 +51444,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 +51490,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 +51541,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 +51552,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 +51612,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..0d205240a5 --- /dev/null +++ b/src/hotspot/cpu/riscv/vtableStubs_riscv.cpp @@ -0,0 +1,260 @@ @@ -56555,7 +51789,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 +51876,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 +51889,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 +51933,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 +51972,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 +52071,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 +52097,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 +52124,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 +52177,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 +52208,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 +52358,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 +52401,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 +52413,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 +52481,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 +52493,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 +52530,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 +52546,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 +52576,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 +52589,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 +52661,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 +52808,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 +52816,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 +52829,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 +52955,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 +53068,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 +53111,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 +53149,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 +53316,7 @@ index 00000000000..3100572e9fd + */ + +#include "precompiled.hpp" ++#include "memory/metaspaceShared.hpp" +#include "runtime/frame.inline.hpp" +#include "runtime/thread.inline.hpp" + @@ -57779,16 +53354,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 +53392,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 +53432,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 +53526,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 +53592,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 +53607,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 +53643,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 +53668,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 +53678,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 +53751,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 +53821,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 +53860,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 +53897,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 +53912,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 +53975,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 +54037,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 +54058,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 +54076,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 +54094,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 +54140,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 +54158,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 +54183,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 +54245,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 +54260,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 +54273,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 +54284,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 +54333,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 +54376,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 +54400,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 +54408,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 +54453,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 +54463,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 +54488,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 +54502,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 34c8d98362..7cf95058fe 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp -@@ -1234,7 +1234,7 @@ class JavaThread: public Thread { +@@ -1259,7 +1259,7 @@ class JavaThread: public Thread { address last_Java_pc(void) { return _anchor.last_Java_pc(); } // Safepoint support @@ -58857,7 +54516,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 +54536,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)) @@ -58914,7 +54573,7 @@ index cf802538689..e8ab3097ac7 100644 #define LITTLE_ENDIAN_ONLY(code) code #define BIG_ENDIAN_ONLY(code) 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 +54659,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 +54679,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 +54690,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 +54701,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 +54746,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 +54756,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 +54771,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 +54789,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 +54885,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 +54939,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 +55033,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 +55087,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 +55139,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 +55200,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 +55254,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 +55304,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 +55483,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 +55493,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 +55501,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 +55512,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 +55552,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 +55650,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 +55879,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 +55919,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 +56439,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 +56476,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 +56504,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 +56562,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 +56572,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 = @@ -60929,7 +56582,7 @@ index 7d7a6107cab..6552ce255fc 100644 for(String s : KNOWN) { if(s.equals(cpu)) 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 +56592,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 +56601,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 +56611,94 @@ index 7805918c28a..823b9f39dbf 100644 if (expectedTestBitInstruction != null) { output.shouldContain(expectedTestBitInstruction); +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 +56708,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 +56716,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 +56726,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 +56736,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 +56744,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 +56754,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 +56764,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 +56772,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 +56782,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 +56792,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 +56800,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 +56810,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 +56820,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 +56854,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 +56884,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 +56896,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 +56906,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 +56918,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 +56950,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 +56958,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 +56966,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 +56994,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 +57014,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 +57034,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 +57054,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 +57074,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 +57094,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 +57114,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 +57134,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 +57154,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 +57173,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 @@ @@ -61487,7 +57252,7 @@ index 7774dabcb5f..7afe3560f30 100644 public static final BooleanSupplier ANY_SHA_INSTRUCTION_AVAILABLE = new OrPredicate(IntrinsicPredicates.SHA1_INSTRUCTION_AVAILABLE, 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 +57262,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 +57272,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 +57282,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 +57291,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 { @@ -61550,7 +57305,7 @@ index 77458554b76..d4bfe31dd7a 100644 OS("isAix", "isLinux", "isOSX", "isSolaris", "isWindows"), VM_TYPE("isClient", "isServer", "isGraal", "isMinimal", "isZero", "isEmbedded"), 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 +57315,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); @@ -61572,10 +57327,10 @@ index 7990c49a1f6..abeff80e5e8 100644 } } 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 +57341,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/openjdk-11.spec b/openjdk-11.spec index 4c6ad12..32b9df0 100644 --- a/openjdk-11.spec +++ b/openjdk-11.spec @@ -762,7 +762,7 @@ Provides: java-src%{?1} = %{epoch}:%{version}-%{release} Name: java-%{javaver}-%{origin} Version: %{newjavaver}.%{buildver} -Release: 0 +Release: 1 # java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons # and this change was brought into RHEL-4. java-1.5.0-ibm packages # also included the epoch in their virtual provides. This created a @@ -1715,6 +1715,9 @@ cjc.mainProgram(arg) %changelog +* Thu July 18 2024 Dingli Zhang - 1.11.0.24.8-1 +- update riscv64 port to 11.0.24 + * Thu July 18 2024 DXwangg - 1.11.0.24.8-0 - update to 11.0.24+8(GA)