diff options
author | 2023-06-23 14:41:35 +0000 | |
---|---|---|
committer | 2023-06-29 07:00:24 +0000 | |
commit | 8838bbf1f5ff911e2663f14ed18660b1c26a010d (patch) | |
tree | e4c92181a39b444d4ff8d46927bb9ef3bbcb4314 | |
parent | 59dd25827bdadeffdeeb23817259a58e7b55e12e (diff) |
riscv64: Enable JNI compiler.
Implement the required `WriteCIE()`, fix a bug in the
`art_jni_dlsym_lookup_critical_stub`, fix reference loads
to be zero-extended and enable the JNI compiler for riscv64.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: run-gtests.sh
Test: testrunner.py --target --64 --ndebug --prebuild --no-prebuild -t 178
Test: # Edit `run-test` to disable checker, then
testrunner.py --target --64 --ndebug --cdex-none --optimizing
# 7 tests fail (pre-existing failures): 004-StackWalk, 137-cfi,
# 2042-reference-processing, 597-deopt-busy-loop, 629-vdex-speed,
# 638-checker-inline-cache-intrinsic and 661-oat-writer-layout.
Test: aosp_cf_riscv64_phone-userdebug boots without crashes.
Bug: 283082089
Change-Id: Ifd47098b7428919b601dd22a130ad1bd51ae516d
-rw-r--r-- | compiler/debug/elf_debug_frame_writer.h | 21 | ||||
-rw-r--r-- | compiler/driver/compiler_options.h | 4 | ||||
-rw-r--r-- | compiler/jni/quick/jni_compiler.cc | 2 | ||||
-rw-r--r-- | compiler/utils/jni_macro_assembler.cc | 18 | ||||
-rw-r--r-- | compiler/utils/jni_macro_assembler.h | 7 | ||||
-rw-r--r-- | compiler/utils/riscv64/jni_macro_assembler_riscv64.cc | 16 | ||||
-rw-r--r-- | compiler/utils/riscv64/jni_macro_assembler_riscv64.h | 3 | ||||
-rw-r--r-- | compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc | 8 | ||||
-rw-r--r-- | runtime/arch/riscv64/jni_entrypoints_riscv64.S | 2 |
9 files changed, 72 insertions, 9 deletions
diff --git a/compiler/debug/elf_debug_frame_writer.h b/compiler/debug/elf_debug_frame_writer.h index 6b72262e26..fe98a578b1 100644 --- a/compiler/debug/elf_debug_frame_writer.h +++ b/compiler/debug/elf_debug_frame_writer.h @@ -90,7 +90,26 @@ static void WriteCIE(InstructionSet isa, /*inout*/ std::vector<uint8_t>* buffer) return; } case InstructionSet::kRiscv64: { - UNIMPLEMENTED(FATAL); + dwarf::DebugFrameOpCodeWriter<> opcodes; + opcodes.DefCFA(Reg::Riscv64Core(2), 0); // X2(SP). + // core registers. + for (int reg = 3; reg < 32; reg++) { // Skip X0 (Zero), X1 (RA) and X2 (SP). + if ((reg >= 5 && reg < 8) || (reg >= 10 && reg < 18) || reg >= 28) { + opcodes.Undefined(Reg::Riscv64Core(reg)); + } else { + opcodes.SameValue(Reg::Riscv64Core(reg)); + } + } + // fp registers. + for (int reg = 0; reg < 32; reg++) { + if (reg < 8 || (reg >=10 && reg < 18) || reg >= 28) { + opcodes.Undefined(Reg::Riscv64Fp(reg)); + } else { + opcodes.SameValue(Reg::Riscv64Fp(reg)); + } + } + auto return_reg = Reg::Riscv64Core(1); // X1(RA). + WriteCIE(is64bit, return_reg, opcodes, buffer); return; } case InstructionSet::kX86: { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index c8a41ce24b..74d081d29e 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -115,9 +115,7 @@ class CompilerOptions final { } bool IsAnyCompilationEnabled() const { - return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_) && - // TODO(riscv64): remove this when we have compiler support for RISC-V - GetInstructionSet() != InstructionSet::kRiscv64; + return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_); } size_t GetHugeMethodThreshold() const { diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc index 03d784bec1..9349d2c9fd 100644 --- a/compiler/jni/quick/jni_compiler.cc +++ b/compiler/jni/quick/jni_compiler.cc @@ -621,7 +621,7 @@ static JniCompiledMethod ArtJniCompileMethodInternal(const CompilerOptions& comp main_jni_conv->CalleeSaveScratchRegisters()[0], kObjectReferenceSize); // Load the declaring class reference. DCHECK_EQ(ArtMethod::DeclaringClassOffset().SizeValue(), 0u); - __ Load(temp, method_register, MemberOffset(0u), kObjectReferenceSize); + __ LoadGcRootWithoutReadBarrier(temp, method_register, MemberOffset(0u)); // Return to main path if the class object is marked. __ TestMarkBit(temp, jclass_read_barrier_return.get(), JNIMacroUnaryCondition::kNotZero); } diff --git a/compiler/utils/jni_macro_assembler.cc b/compiler/utils/jni_macro_assembler.cc index a0230e37fe..dc7ec60032 100644 --- a/compiler/utils/jni_macro_assembler.cc +++ b/compiler/utils/jni_macro_assembler.cc @@ -37,6 +37,7 @@ #include "base/casts.h" #include "base/globals.h" #include "base/memory_region.h" +#include "gc_root.h" namespace art HIDDEN { @@ -97,4 +98,21 @@ MacroAsm64UniquePtr JNIMacroAssembler<PointerSize::k64>::Create( } } +template <PointerSize kPointerSize> +void JNIMacroAssembler<kPointerSize>::LoadGcRootWithoutReadBarrier(ManagedRegister dest, + ManagedRegister base, + MemberOffset offs) { + static_assert(sizeof(uint32_t) == sizeof(GcRoot<mirror::Object>)); + Load(dest, base, offs, sizeof(uint32_t)); +} + +template +void JNIMacroAssembler<PointerSize::k32>::LoadGcRootWithoutReadBarrier(ManagedRegister dest, + ManagedRegister base, + MemberOffset offs); +template +void JNIMacroAssembler<PointerSize::k64>::LoadGcRootWithoutReadBarrier(ManagedRegister dest, + ManagedRegister base, + MemberOffset offs); + } // namespace art diff --git a/compiler/utils/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h index 286c378670..2d51439ee8 100644 --- a/compiler/utils/jni_macro_assembler.h +++ b/compiler/utils/jni_macro_assembler.h @@ -129,9 +129,14 @@ class JNIMacroAssembler : public DeletableArenaObject<kArenaAllocAssembler> { // Load routines virtual void Load(ManagedRegister dest, FrameOffset src, size_t size) = 0; virtual void Load(ManagedRegister dest, ManagedRegister base, MemberOffset offs, size_t size) = 0; - virtual void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset<kPointerSize> offs) = 0; + // Load reference from a `GcRoot<>`. The default is to load as `jint`. Some architectures + // (say, RISC-V) override this to provide a different sign- or zero-extension. + virtual void LoadGcRootWithoutReadBarrier(ManagedRegister dest, + ManagedRegister base, + MemberOffset offs); + // Copying routines // Move arguments from `srcs` locations to `dests` locations. diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc b/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc index a05e9b49f4..d7e8030fa0 100644 --- a/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc +++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc @@ -236,6 +236,14 @@ void Riscv64JNIMacroAssembler::LoadRawPtrFromThread(ManagedRegister m_dest, Thre Load(m_dest, tr, MemberOffset(offs.Int32Value()), static_cast<size_t>(kRiscv64PointerSize)); } +void Riscv64JNIMacroAssembler::LoadGcRootWithoutReadBarrier(ManagedRegister m_dest, + ManagedRegister m_base, + MemberOffset offs) { + Riscv64ManagedRegister base = m_base.AsRiscv64(); + Riscv64ManagedRegister dest = m_dest.AsRiscv64(); + __ Loadwu(dest.AsXRegister(), base.AsXRegister(), offs.Int32Value()); +} + void Riscv64JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs, ArrayRef<FrameOffset> refs) { @@ -291,7 +299,13 @@ void Riscv64JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests, ? src.GetRegister().AsRiscv64() : Riscv64ManagedRegister::FromXRegister(TMP2); if (!src.IsRegister()) { - Load(reg, src.GetFrameOffset(), src.GetSize()); + if (ref != kInvalidReferenceOffset) { + // We're loading the reference only for comparison with null, so it does not matter + // if we sign- or zero-extend but let's correctly zero-extend the reference anyway. + __ Loadwu(reg.AsRiscv64().AsXRegister(), SP, src.GetFrameOffset().SizeValue()); + } else { + Load(reg, src.GetFrameOffset(), src.GetSize()); + } } if (ref != kInvalidReferenceOffset) { DCHECK_NE(i, 0u); diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64.h b/compiler/utils/riscv64/jni_macro_assembler_riscv64.h index 93c0001e6f..79618e2c8e 100644 --- a/compiler/utils/riscv64/jni_macro_assembler_riscv64.h +++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64.h @@ -68,6 +68,9 @@ class Riscv64JNIMacroAssembler : public JNIMacroAssemblerFwd<Riscv64Assembler, void Load(ManagedRegister dest, FrameOffset offs, size_t size) override; void Load(ManagedRegister dest, ManagedRegister base, MemberOffset offs, size_t size) override; void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset64 offs) override; + void LoadGcRootWithoutReadBarrier(ManagedRegister dest, + ManagedRegister base, + MemberOffset offs) override; // Copying routines. void MoveArguments(ArrayRef<ArgumentLocation> dests, diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc b/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc index 8aa41565d8..ec5bb9d818 100644 --- a/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc +++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64_test.cc @@ -266,6 +266,12 @@ TEST_F(JniMacroAssemblerRiscv64Test, Load) { expected += "addi t6, s1, 0x7f8\n" "ld s11, 0x408(t6)\n"; + __ LoadGcRootWithoutReadBarrier(AsManaged(T0), AsManaged(A0), MemberOffset(0)); + expected += "lwu t0, 0(a0)\n"; + __ LoadGcRootWithoutReadBarrier(AsManaged(T1), AsManaged(S2), MemberOffset(0x800)); + expected += "addi t6, s2, 0x7f8\n" + "lwu t1, 8(t6)\n"; + DriverStr(expected, "Load"); } @@ -428,7 +434,7 @@ TEST_F(JniMacroAssemblerRiscv64Test, MoveArguments) { "1:\n" "ld t5, 76(sp)\n" "sd t5, 0(sp)\n" - "lw t5, 84(sp)\n" + "lwu t5, 84(sp)\n" "beqz t5, 2f\n" "addi t5, sp, 84\n" "2:\n" diff --git a/runtime/arch/riscv64/jni_entrypoints_riscv64.S b/runtime/arch/riscv64/jni_entrypoints_riscv64.S index 92289be935..c9d034b6cc 100644 --- a/runtime/arch/riscv64/jni_entrypoints_riscv64.S +++ b/runtime/arch/riscv64/jni_entrypoints_riscv64.S @@ -348,7 +348,7 @@ ENTRY art_jni_dlsym_lookup_critical_stub sd t3, FRAME_SIZE_SAVE_REFS_AND_ARGS+0(t1) sd t4, FRAME_SIZE_SAVE_REFS_AND_ARGS+8(t1) addi t1, t1, -16 - bnez t2, .Lcritical_skip_copy_args_back + bnez t2, .Lcritical_copy_args_back_loop .Lcritical_skip_copy_args_back: // Remove the frame reservation. |