diff options
author | 2023-03-15 16:05:13 +0800 | |
---|---|---|
committer | 2023-06-12 06:48:13 +0000 | |
commit | d3c94f5b364d973af070bcd638d1566d741a8351 (patch) | |
tree | f482a3e8d0e3a294d9ce992dd450da32baa8bef9 | |
parent | e8e8dacad6f5da4300c526b80d8e6ca9f74dbef9 (diff) |
Add jni macro assembler skeleton for riscv64.
Note: Most functions are unimplemeted.
Test: m test-art-host-gtest
Bug: 283082089
Signed-off-by: Lifang Xia <lifang_xia@linux.alibaba.com>
Signed-off-by: Wendong Wang <wangwd@xcvmbyte.com>
Change-Id: Ifb0c6c15bd9e1159ea2c90edc306335ca634c1d8
-rw-r--r-- | compiler/Android.bp | 1 | ||||
-rw-r--r-- | compiler/utils/jni_macro_assembler.cc | 7 | ||||
-rw-r--r-- | compiler/utils/riscv64/jni_macro_assembler_riscv64.cc | 273 | ||||
-rw-r--r-- | compiler/utils/riscv64/jni_macro_assembler_riscv64.h | 155 |
4 files changed, 436 insertions, 0 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index acb15d9604..00e1bb9713 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -132,6 +132,7 @@ art_cc_defaults { riscv64: { srcs: [ "utils/riscv64/assembler_riscv64.cc", + "utils/riscv64/jni_macro_assembler_riscv64.cc", "utils/riscv64/managed_register_riscv64.cc", ], }, diff --git a/compiler/utils/jni_macro_assembler.cc b/compiler/utils/jni_macro_assembler.cc index 8b47b38e63..a0230e37fe 100644 --- a/compiler/utils/jni_macro_assembler.cc +++ b/compiler/utils/jni_macro_assembler.cc @@ -25,6 +25,9 @@ #ifdef ART_ENABLE_CODEGEN_arm64 #include "arm64/jni_macro_assembler_arm64.h" #endif +#ifdef ART_ENABLE_CODEGEN_riscv64 +#include "riscv64/jni_macro_assembler_riscv64.h" +#endif #ifdef ART_ENABLE_CODEGEN_x86 #include "x86/jni_macro_assembler_x86.h" #endif @@ -79,6 +82,10 @@ MacroAsm64UniquePtr JNIMacroAssembler<PointerSize::k64>::Create( case InstructionSet::kArm64: return MacroAsm64UniquePtr(new (allocator) arm64::Arm64JNIMacroAssembler(allocator)); #endif +#ifdef ART_ENABLE_CODEGEN_riscv64 + case InstructionSet::kRiscv64: + return MacroAsm64UniquePtr(new (allocator) riscv64::Riscv64JNIMacroAssembler(allocator)); +#endif #ifdef ART_ENABLE_CODEGEN_x86_64 case InstructionSet::kX86_64: return MacroAsm64UniquePtr(new (allocator) x86_64::X86_64JNIMacroAssembler(allocator)); diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc b/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc new file mode 100644 index 0000000000..689d871ed8 --- /dev/null +++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64.cc @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "jni_macro_assembler_riscv64.h" + +#include "entrypoints/quick/quick_entrypoints.h" +#include "managed_register_riscv64.h" +#include "offsets.h" +#include "thread.h" + +namespace art { +namespace riscv64 { + +#define __ asm_. + +Riscv64JNIMacroAssembler::~Riscv64JNIMacroAssembler() { +} + +void Riscv64JNIMacroAssembler::FinalizeCode() { + __ FinalizeCode(); +} + +void Riscv64JNIMacroAssembler::BuildFrame(size_t frame_size, + ManagedRegister method_reg, + ArrayRef<const ManagedRegister> callee_save_regs) { + // TODO(riscv64): Implement this. + UNUSED(frame_size, method_reg, callee_save_regs); +} + +void Riscv64JNIMacroAssembler::RemoveFrame(size_t frame_size, + ArrayRef<const ManagedRegister> callee_save_regs, + bool may_suspend) { + // TODO(riscv64): Implement this. + UNUSED(frame_size, callee_save_regs, may_suspend); +} + +void Riscv64JNIMacroAssembler::IncreaseFrameSize(size_t adjust) { + if (adjust != 0u) { + CHECK_ALIGNED(adjust, kStackAlignment); + __ AddConst64(SP, SP, -adjust); + __ cfi().AdjustCFAOffset(adjust); + } +} + +void Riscv64JNIMacroAssembler::DecreaseFrameSize(size_t adjust) { + if (adjust != 0u) { + CHECK_ALIGNED(adjust, kStackAlignment); + __ AddConst64(SP, SP, adjust); + __ cfi().AdjustCFAOffset(-adjust); + } +} + +ManagedRegister Riscv64JNIMacroAssembler::CoreRegisterWithSize(ManagedRegister src, size_t size) { + DCHECK(src.AsRiscv64().IsXRegister()); + DCHECK(size == 4u || size == 8u) << size; + return src; +} + +void Riscv64JNIMacroAssembler::Store(FrameOffset offs, ManagedRegister m_src, size_t size) { + // TODO(riscv64): Implement this. + UNUSED(offs, m_src, size); +} + +void Riscv64JNIMacroAssembler::Store(ManagedRegister base, + MemberOffset offs, + ManagedRegister m_src, + size_t size) { + // TODO(riscv64): Implement this. + UNUSED(base, offs, m_src, size); +} + +void Riscv64JNIMacroAssembler::StoreRawPtr(FrameOffset offs, ManagedRegister m_src) { + // TODO(riscv64): Implement this. + UNUSED(offs, m_src); +} + +void Riscv64JNIMacroAssembler::StoreStackPointerToThread(ThreadOffset64 thr_offs, bool tag_sp) { + // TODO(riscv64): Implement this. + UNUSED(thr_offs, tag_sp); +} + +void Riscv64JNIMacroAssembler::Load(ManagedRegister m_dest, FrameOffset src, size_t size) { + // TODO(riscv64): Implement this. + UNUSED(m_dest, src, size); +} + +void Riscv64JNIMacroAssembler::Load(ManagedRegister m_dest, + ManagedRegister m_base, + MemberOffset offs, + size_t size) { + // TODO(riscv64): Implement this. + UNUSED(m_dest, m_base, offs, size); +} + +void Riscv64JNIMacroAssembler::LoadRawPtrFromThread(ManagedRegister m_dest, ThreadOffset64 offs) { + // TODO(riscv64): Implement this. + UNUSED(m_dest, offs); +} + +void Riscv64JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests, + ArrayRef<ArgumentLocation> srcs, + ArrayRef<FrameOffset> refs) { + // TODO(riscv64): Implement this. + UNUSED(dests, srcs, refs); +} + +void Riscv64JNIMacroAssembler::Move(ManagedRegister m_dest, ManagedRegister m_src, size_t size) { + // TODO(riscv64): Implement this. + UNUSED(m_dest, m_src, size); +} + +void Riscv64JNIMacroAssembler::Move(ManagedRegister m_dest, size_t value) { + // TODO(riscv64): Implement this. + UNUSED(m_dest, value); +} + +void Riscv64JNIMacroAssembler::SignExtend(ManagedRegister mreg, size_t size) { + // TODO(riscv64): Implement this. + UNUSED(mreg, size); +} + +void Riscv64JNIMacroAssembler::ZeroExtend(ManagedRegister mreg, size_t size) { + // TODO(riscv64): Implement this. + UNUSED(mreg, size); +} + +void Riscv64JNIMacroAssembler::GetCurrentThread(ManagedRegister tr) { + // TODO(riscv64): Implement this. + UNUSED(tr); +} + +void Riscv64JNIMacroAssembler::GetCurrentThread(FrameOffset offset) { + // TODO(riscv64): Implement this. + UNUSED(offset); +} + +void Riscv64JNIMacroAssembler::DecodeJNITransitionOrLocalJObject(ManagedRegister m_reg, + JNIMacroLabel* slow_path, + JNIMacroLabel* resume) { + // TODO(riscv64): Implement this. + UNUSED(m_reg, slow_path, resume); +} + +void Riscv64JNIMacroAssembler::VerifyObject([[maybe_unused]] ManagedRegister m_src, + [[maybe_unused]] bool could_be_null) { + // TODO: not validating references. +} + +void Riscv64JNIMacroAssembler::VerifyObject([[maybe_unused]] FrameOffset src, + [[maybe_unused]] bool could_be_null) { + // TODO: not validating references. +} + +void Riscv64JNIMacroAssembler::Jump(ManagedRegister m_base, Offset offs) { + Riscv64ManagedRegister base = m_base.AsRiscv64(); + CHECK(base.IsXRegister()) << base; + XRegister scratch = TMP; + __ Loadd(scratch, base.AsXRegister(), offs.Int32Value()); + __ Jr(scratch); +} + +void Riscv64JNIMacroAssembler::Call(ManagedRegister m_base, Offset offs) { + Riscv64ManagedRegister base = m_base.AsRiscv64(); + CHECK(base.IsXRegister()) << base; + XRegister scratch = TMP; + __ Loadd(scratch, base.AsXRegister(), offs.Int32Value()); + __ Jalr(scratch); +} + + +void Riscv64JNIMacroAssembler::CallFromThread(ThreadOffset64 offset) { + Call(Riscv64ManagedRegister::FromXRegister(TR), offset); +} + +void Riscv64JNIMacroAssembler::TryToTransitionFromRunnableToNative( + JNIMacroLabel* label, + ArrayRef<const ManagedRegister> scratch_regs) { + // TODO(riscv64): Implement this. + UNUSED(label, scratch_regs); +} + +void Riscv64JNIMacroAssembler::TryToTransitionFromNativeToRunnable( + JNIMacroLabel* label, + ArrayRef<const ManagedRegister> scratch_regs, + ManagedRegister return_reg) { + // TODO(riscv64): Implement this. + UNUSED(label, scratch_regs, return_reg); +} + +void Riscv64JNIMacroAssembler::SuspendCheck(JNIMacroLabel* label) { + // TODO(riscv64): Implement this. + UNUSED(label); +} + +void Riscv64JNIMacroAssembler::ExceptionPoll(JNIMacroLabel* label) { + // TODO(riscv64): Implement this. + UNUSED(label); +} + +void Riscv64JNIMacroAssembler::DeliverPendingException() { + // TODO(riscv64): Implement this. +} + +std::unique_ptr<JNIMacroLabel> Riscv64JNIMacroAssembler::CreateLabel() { + return std::unique_ptr<JNIMacroLabel>(new Riscv64JNIMacroLabel()); +} + +void Riscv64JNIMacroAssembler::Jump(JNIMacroLabel* label) { + CHECK(label != nullptr); + __ J(down_cast<Riscv64Label*>(Riscv64JNIMacroLabel::Cast(label)->AsRiscv64())); +} + +void Riscv64JNIMacroAssembler::TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) { + CHECK(label != nullptr); + + DCHECK_EQ(Thread::IsGcMarkingSize(), 4u); + DCHECK(gUseReadBarrier); + + XRegister test_reg = TMP; + int32_t is_gc_marking_offset = Thread::IsGcMarkingOffset<kArm64PointerSize>().Int32Value(); + __ Loadw(test_reg, TR, is_gc_marking_offset); + switch (cond) { + case JNIMacroUnaryCondition::kZero: + __ Beqz(test_reg, down_cast<Riscv64Label*>(Riscv64JNIMacroLabel::Cast(label)->AsRiscv64())); + break; + case JNIMacroUnaryCondition::kNotZero: + __ Bnez(test_reg, down_cast<Riscv64Label*>(Riscv64JNIMacroLabel::Cast(label)->AsRiscv64())); + break; + default: + LOG(FATAL) << "Not implemented unary condition: " << static_cast<int>(cond); + UNREACHABLE(); + } +} + +void Riscv64JNIMacroAssembler::TestMarkBit(ManagedRegister ref, + JNIMacroLabel* label, + JNIMacroUnaryCondition cond) { + // TODO(riscv64): Implement this. + UNUSED(ref, label, cond); +} + +void Riscv64JNIMacroAssembler::TestByteAndJumpIfNotZero(uintptr_t address, JNIMacroLabel* label) { + XRegister test_reg = TMP; + int32_t small_offset = dchecked_integral_cast<int32_t>(address & 0xfff) - + dchecked_integral_cast<int32_t>((address & 0x800) << 1); + int32_t remainder = static_cast<int64_t>(address) - small_offset; + __ Li(test_reg, remainder); + __ Lb(test_reg, test_reg, small_offset); + __ Bnez(test_reg, down_cast<Riscv64Label*>(Riscv64JNIMacroLabel::Cast(label)->AsRiscv64())); +} + +void Riscv64JNIMacroAssembler::Bind(JNIMacroLabel* label) { + CHECK(label != nullptr); + __ Bind(Riscv64JNIMacroLabel::Cast(label)->AsRiscv64()); +} + +#undef ___ + +} // namespace riscv64 +} // namespace art diff --git a/compiler/utils/riscv64/jni_macro_assembler_riscv64.h b/compiler/utils/riscv64/jni_macro_assembler_riscv64.h new file mode 100644 index 0000000000..e472526f54 --- /dev/null +++ b/compiler/utils/riscv64/jni_macro_assembler_riscv64.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ +#define ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ + +#include <stdint.h> +#include <memory> +#include <vector> + +#include <android-base/logging.h> + +#include "assembler_riscv64.h" +#include "base/arena_containers.h" +#include "base/enums.h" +#include "base/macros.h" +#include "offsets.h" +#include "utils/assembler.h" +#include "utils/jni_macro_assembler.h" + +namespace art { +namespace riscv64 { + +class Riscv64JNIMacroAssembler : public JNIMacroAssemblerFwd<Riscv64Assembler, PointerSize::k64> { + public: + explicit Riscv64JNIMacroAssembler(ArenaAllocator* allocator) + : JNIMacroAssemblerFwd<Riscv64Assembler, PointerSize::k64>(allocator) {} + ~Riscv64JNIMacroAssembler(); + + // Finalize the code. + void FinalizeCode() override; + + // Emit code that will create an activation on the stack. + void BuildFrame(size_t frame_size, + ManagedRegister method_reg, + ArrayRef<const ManagedRegister> callee_save_regs) override; + + // Emit code that will remove an activation from the stack. + void RemoveFrame(size_t frame_size, + ArrayRef<const ManagedRegister> callee_save_regs, + bool may_suspend) override; + + void IncreaseFrameSize(size_t adjust) override; + void DecreaseFrameSize(size_t adjust) override; + + ManagedRegister CoreRegisterWithSize(ManagedRegister src, size_t size) override; + + // Store routines. + void Store(FrameOffset offs, ManagedRegister src, size_t size) override; + void Store(ManagedRegister base, MemberOffset offs, ManagedRegister src, size_t size) override; + void StoreRawPtr(FrameOffset dest, ManagedRegister src) override; + void StoreStackPointerToThread(ThreadOffset64 thr_offs, bool tag_sp) override; + + // Load routines. + void Load(ManagedRegister dest, FrameOffset src, size_t size) override; + void Load(ManagedRegister dest, ManagedRegister base, MemberOffset offs, size_t size) override; + void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset64 offs) override; + + // Copying routines. + void MoveArguments(ArrayRef<ArgumentLocation> dests, + ArrayRef<ArgumentLocation> srcs, + ArrayRef<FrameOffset> refs) override; + void Move(ManagedRegister dest, ManagedRegister src, size_t size) override; + void Move(ManagedRegister dest, size_t value) override; + + // Sign extension. + void SignExtend(ManagedRegister mreg, size_t size) override; + + // Zero extension. + void ZeroExtend(ManagedRegister mreg, size_t size) override; + + // Exploit fast access in managed code to Thread::Current(). + void GetCurrentThread(ManagedRegister tr) override; + void GetCurrentThread(FrameOffset dest_offset) override; + + // Decode JNI transition or local `jobject`. For (weak) global `jobject`, jump to slow path. + void DecodeJNITransitionOrLocalJObject(ManagedRegister reg, + JNIMacroLabel* slow_path, + JNIMacroLabel* resume) override; + + // Heap::VerifyObject on src. In some cases (such as a reference to this) we + // know that src may not be null. + void VerifyObject(ManagedRegister src, bool could_be_null) override; + void VerifyObject(FrameOffset src, bool could_be_null) override; + + // Jump to address held at [base+offset] (used for tail calls). + void Jump(ManagedRegister base, Offset offset) override; + + // Call to address held at [base+offset]. + void Call(ManagedRegister base, Offset offset) override; + void CallFromThread(ThreadOffset64 offset) override; + + // Generate fast-path for transition to Native. Go to `label` if any thread flag is set. + // The implementation can use `scratch_regs` which should be callee save core registers + // (already saved before this call) and must preserve all argument registers. + void TryToTransitionFromRunnableToNative(JNIMacroLabel* label, + ArrayRef<const ManagedRegister> scratch_regs) override; + + // Generate fast-path for transition to Runnable. Go to `label` if any thread flag is set. + // The implementation can use `scratch_regs` which should be core argument registers + // not used as return registers and it must preserve the `return_reg` if any. + void TryToTransitionFromNativeToRunnable(JNIMacroLabel* label, + ArrayRef<const ManagedRegister> scratch_regs, + ManagedRegister return_reg) override; + + // Generate suspend check and branch to `label` if there is a pending suspend request. + void SuspendCheck(JNIMacroLabel* label) override; + + // Generate code to check if Thread::Current()->exception_ is non-null + // and branch to the `label` if it is. + void ExceptionPoll(JNIMacroLabel* label) override; + // Deliver pending exception. + void DeliverPendingException() override; + + // Create a new label that can be used with Jump/Bind calls. + std::unique_ptr<JNIMacroLabel> CreateLabel() override; + // Emit an unconditional jump to the label. + void Jump(JNIMacroLabel* label) override; + // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag. + void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override; + // Emit a conditional jump to the label by applying a unary condition test to object's mark bit. + void TestMarkBit(ManagedRegister ref, JNIMacroLabel* label, JNIMacroUnaryCondition cond) override; + // Emit a conditional jump to label if the loaded value from specified locations is not zero. + void TestByteAndJumpIfNotZero(uintptr_t address, JNIMacroLabel* label) override; + // Code at this offset will serve as the target for the Jump call. + void Bind(JNIMacroLabel* label) override; +}; + +class Riscv64JNIMacroLabel final + : public JNIMacroLabelCommon<Riscv64JNIMacroLabel, + art::Label, + InstructionSet::kRiscv64> { + public: + art::Label* AsRiscv64() { + return AsPlatformLabel(); + } +}; + +} // namespace riscv64 +} // namespace art + +#endif // ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ |