1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ 18 #define ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ 19 20 #include <stdint.h> 21 #include <memory> 22 #include <vector> 23 24 #include <android-base/logging.h> 25 26 #include "assembler_riscv64.h" 27 #include "base/arena_containers.h" 28 #include "base/macros.h" 29 #include "base/pointer_size.h" 30 #include "offsets.h" 31 #include "utils/assembler.h" 32 #include "utils/jni_macro_assembler.h" 33 34 namespace art HIDDEN { 35 namespace riscv64 { 36 37 class Riscv64JNIMacroAssembler : public JNIMacroAssemblerFwd<Riscv64Assembler, PointerSize::k64> { 38 public: Riscv64JNIMacroAssembler(ArenaAllocator * allocator)39 explicit Riscv64JNIMacroAssembler(ArenaAllocator* allocator) 40 : JNIMacroAssemblerFwd<Riscv64Assembler, PointerSize::k64>(allocator) {} 41 ~Riscv64JNIMacroAssembler(); 42 43 // Finalize the code. 44 void FinalizeCode() override; 45 46 // Emit code that will create an activation on the stack. 47 void BuildFrame(size_t frame_size, 48 ManagedRegister method_reg, 49 ArrayRef<const ManagedRegister> callee_save_regs) override; 50 51 // Emit code that will remove an activation from the stack. 52 void RemoveFrame(size_t frame_size, 53 ArrayRef<const ManagedRegister> callee_save_regs, 54 bool may_suspend) override; 55 56 void IncreaseFrameSize(size_t adjust) override; 57 void DecreaseFrameSize(size_t adjust) override; 58 59 ManagedRegister CoreRegisterWithSize(ManagedRegister src, size_t size) override; 60 61 // Store routines. 62 void Store(FrameOffset offs, ManagedRegister src, size_t size) override; 63 void Store(ManagedRegister base, MemberOffset offs, ManagedRegister src, size_t size) override; 64 void StoreRawPtr(FrameOffset offs, ManagedRegister src) override; 65 void StoreStackPointerToThread(ThreadOffset64 offs, bool tag_sp) override; 66 67 // Load routines. 68 void Load(ManagedRegister dest, FrameOffset offs, size_t size) override; 69 void Load(ManagedRegister dest, ManagedRegister base, MemberOffset offs, size_t size) override; 70 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset64 offs) override; 71 void LoadGcRootWithoutReadBarrier(ManagedRegister dest, 72 ManagedRegister base, 73 MemberOffset offs) override; 74 void LoadStackReference(ManagedRegister dest, FrameOffset offs) override; 75 76 // Copying routines. 77 void MoveArguments(ArrayRef<ArgumentLocation> dests, 78 ArrayRef<ArgumentLocation> srcs, 79 ArrayRef<FrameOffset> refs) override; 80 void Move(ManagedRegister dest, ManagedRegister src, size_t size) override; 81 void Move(ManagedRegister dest, size_t value) override; 82 83 // Sign extension. 84 void SignExtend(ManagedRegister mreg, size_t size) override; 85 86 // Zero extension. 87 void ZeroExtend(ManagedRegister mreg, size_t size) override; 88 89 // Exploit fast access in managed code to Thread::Current(). 90 void GetCurrentThread(ManagedRegister dest) override; 91 void GetCurrentThread(FrameOffset offset) override; 92 93 // Decode JNI transition or local `jobject`. For (weak) global `jobject`, jump to slow path. 94 void DecodeJNITransitionOrLocalJObject(ManagedRegister reg, 95 JNIMacroLabel* slow_path, 96 JNIMacroLabel* resume) override; 97 98 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 99 // know that src may not be null. 100 void VerifyObject(ManagedRegister src, bool could_be_null) override; 101 void VerifyObject(FrameOffset src, bool could_be_null) override; 102 103 // Jump to address held at [base+offset] (used for tail calls). 104 void Jump(ManagedRegister base, Offset offset) override; 105 106 // Call to address held at [base+offset]. 107 void Call(ManagedRegister base, Offset offset) override; 108 void CallFromThread(ThreadOffset64 offset) override; 109 110 // Generate fast-path for transition to Native. Go to `label` if any thread flag is set. 111 // The implementation can use `scratch_regs` which should be callee save core registers 112 // (already saved before this call) and must preserve all argument registers. 113 void TryToTransitionFromRunnableToNative(JNIMacroLabel* label, 114 ArrayRef<const ManagedRegister> scratch_regs) override; 115 116 // Generate fast-path for transition to Runnable. Go to `label` if any thread flag is set. 117 // The implementation can use `scratch_regs` which should be core argument registers 118 // not used as return registers and it must preserve the `return_reg` if any. 119 void TryToTransitionFromNativeToRunnable(JNIMacroLabel* label, 120 ArrayRef<const ManagedRegister> scratch_regs, 121 ManagedRegister return_reg) override; 122 123 // Generate suspend check and branch to `label` if there is a pending suspend request. 124 void SuspendCheck(JNIMacroLabel* label) override; 125 126 // Generate code to check if Thread::Current()->exception_ is non-null 127 // and branch to the `label` if it is. 128 void ExceptionPoll(JNIMacroLabel* label) override; 129 // Deliver pending exception. 130 void DeliverPendingException() override; 131 132 // Create a new label that can be used with Jump/Bind calls. 133 std::unique_ptr<JNIMacroLabel> CreateLabel() override; 134 // Emit an unconditional jump to the label. 135 void Jump(JNIMacroLabel* label) override; 136 // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag. 137 void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override; 138 // Emit a conditional jump to the label by applying a unary condition test to object's mark bit. 139 void TestMarkBit(ManagedRegister ref, JNIMacroLabel* label, JNIMacroUnaryCondition cond) override; 140 // Emit a conditional jump to label if the loaded value from specified locations is not zero. 141 void TestByteAndJumpIfNotZero(uintptr_t address, JNIMacroLabel* label) override; 142 // Code at this offset will serve as the target for the Jump call. 143 void Bind(JNIMacroLabel* label) override; 144 145 private: 146 void CreateJObject(ManagedRegister m_dest, 147 FrameOffset spilled_reference_offset, 148 ManagedRegister m_ref, 149 bool null_allowed); 150 151 ART_FRIEND_TEST(JniMacroAssemblerRiscv64Test, CreateJObject); 152 }; 153 154 class Riscv64JNIMacroLabel final 155 : public JNIMacroLabelCommon<Riscv64JNIMacroLabel, 156 Riscv64Label, 157 InstructionSet::kRiscv64> { 158 public: AsRiscv64()159 Riscv64Label* AsRiscv64() { 160 return AsPlatformLabel(); 161 } 162 }; 163 164 } // namespace riscv64 165 } // namespace art 166 167 #endif // ART_COMPILER_UTILS_RISCV64_JNI_MACRO_ASSEMBLER_RISCV64_H_ 168