1 /* 2 * Copyright (C) 2016 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_ARM_JNI_MACRO_ASSEMBLER_ARM_VIXL_H_ 18 #define ART_COMPILER_UTILS_ARM_JNI_MACRO_ASSEMBLER_ARM_VIXL_H_ 19 20 #include <android-base/logging.h> 21 22 #include "base/arena_containers.h" 23 #include "base/macros.h" 24 #include "constants_arm.h" 25 #include "offsets.h" 26 #include "utils/arm/assembler_arm_shared.h" 27 #include "utils/arm/assembler_arm_vixl.h" 28 #include "utils/arm/managed_register_arm.h" 29 #include "utils/assembler.h" 30 #include "utils/jni_macro_assembler.h" 31 32 namespace art { 33 namespace arm { 34 35 class ArmVIXLJNIMacroAssembler final 36 : public JNIMacroAssemblerFwd<ArmVIXLAssembler, PointerSize::k32> { 37 private: 38 class ArmException; 39 public: ArmVIXLJNIMacroAssembler(ArenaAllocator * allocator)40 explicit ArmVIXLJNIMacroAssembler(ArenaAllocator* allocator) 41 : JNIMacroAssemblerFwd(allocator), 42 exception_blocks_(allocator->Adapter(kArenaAllocAssembler)) {} 43 ~ArmVIXLJNIMacroAssembler()44 virtual ~ArmVIXLJNIMacroAssembler() {} 45 void FinalizeCode() override; 46 47 // 48 // Overridden common assembler high-level functionality 49 // 50 51 // Emit code that will create an activation on the stack. 52 void BuildFrame(size_t frame_size, 53 ManagedRegister method_reg, 54 ArrayRef<const ManagedRegister> callee_save_regs, 55 const ManagedRegisterEntrySpills& entry_spills) override; 56 57 // Emit code that will remove an activation from the stack. 58 void RemoveFrame(size_t frame_size, 59 ArrayRef<const ManagedRegister> callee_save_regs, 60 bool may_suspend) override; 61 62 void IncreaseFrameSize(size_t adjust) override; 63 void DecreaseFrameSize(size_t adjust) override; 64 65 // Store routines. 66 void Store(FrameOffset offs, ManagedRegister src, size_t size) override; 67 void StoreRef(FrameOffset dest, ManagedRegister src) override; 68 void StoreRawPtr(FrameOffset dest, ManagedRegister src) override; 69 70 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm, ManagedRegister scratch) override; 71 72 void StoreStackOffsetToThread(ThreadOffset32 thr_offs, 73 FrameOffset fr_offs, 74 ManagedRegister scratch) override; 75 76 void StoreStackPointerToThread(ThreadOffset32 thr_offs) override; 77 78 void StoreSpanning(FrameOffset dest, 79 ManagedRegister src, 80 FrameOffset in_off, 81 ManagedRegister scratch) override; 82 83 // Load routines. 84 void Load(ManagedRegister dest, FrameOffset src, size_t size) override; 85 86 void LoadFromThread(ManagedRegister dest, 87 ThreadOffset32 src, 88 size_t size) override; 89 90 void LoadRef(ManagedRegister dest, FrameOffset src) override; 91 92 void LoadRef(ManagedRegister dest, 93 ManagedRegister base, 94 MemberOffset offs, 95 bool unpoison_reference) override; 96 97 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) override; 98 99 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset32 offs) override; 100 101 // Copying routines. 102 void Move(ManagedRegister dest, ManagedRegister src, size_t size) override; 103 104 void CopyRawPtrFromThread(FrameOffset fr_offs, 105 ThreadOffset32 thr_offs, 106 ManagedRegister scratch) override; 107 108 void CopyRawPtrToThread(ThreadOffset32 thr_offs, 109 FrameOffset fr_offs, 110 ManagedRegister scratch) override; 111 112 void CopyRef(FrameOffset dest, FrameOffset src, ManagedRegister scratch) override; 113 114 void Copy(FrameOffset dest, FrameOffset src, ManagedRegister scratch, size_t size) override; 115 116 void Copy(FrameOffset dest, 117 ManagedRegister src_base, 118 Offset src_offset, 119 ManagedRegister scratch, 120 size_t size) override; 121 122 void Copy(ManagedRegister dest_base, 123 Offset dest_offset, 124 FrameOffset src, 125 ManagedRegister scratch, 126 size_t size) override; 127 128 void Copy(FrameOffset dest, 129 FrameOffset src_base, 130 Offset src_offset, 131 ManagedRegister scratch, 132 size_t size) override; 133 134 void Copy(ManagedRegister dest, 135 Offset dest_offset, 136 ManagedRegister src, 137 Offset src_offset, 138 ManagedRegister scratch, 139 size_t size) override; 140 141 void Copy(FrameOffset dest, 142 Offset dest_offset, 143 FrameOffset src, 144 Offset src_offset, 145 ManagedRegister scratch, 146 size_t size) override; 147 148 // Sign extension. 149 void SignExtend(ManagedRegister mreg, size_t size) override; 150 151 // Zero extension. 152 void ZeroExtend(ManagedRegister mreg, size_t size) override; 153 154 // Exploit fast access in managed code to Thread::Current(). 155 void GetCurrentThread(ManagedRegister mtr) override; 156 void GetCurrentThread(FrameOffset dest_offset, 157 ManagedRegister scratch) override; 158 159 // Set up out_reg to hold a Object** into the handle scope, or to be null if the 160 // value is null and null_allowed. in_reg holds a possibly stale reference 161 // that can be used to avoid loading the handle scope entry to see if the value is 162 // null. 163 void CreateHandleScopeEntry(ManagedRegister out_reg, 164 FrameOffset handlescope_offset, 165 ManagedRegister in_reg, 166 bool null_allowed) override; 167 168 // Set up out_off to hold a Object** into the handle scope, or to be null if the 169 // value is null and null_allowed. 170 void CreateHandleScopeEntry(FrameOffset out_off, 171 FrameOffset handlescope_offset, 172 ManagedRegister scratch, 173 bool null_allowed) override; 174 175 // src holds a handle scope entry (Object**) load this into dst. 176 void LoadReferenceFromHandleScope(ManagedRegister dst, 177 ManagedRegister src) override; 178 179 // Heap::VerifyObject on src. In some cases (such as a reference to this) we 180 // know that src may not be null. 181 void VerifyObject(ManagedRegister src, bool could_be_null) override; 182 void VerifyObject(FrameOffset src, bool could_be_null) override; 183 184 // Call to address held at [base+offset]. 185 void Call(ManagedRegister base, Offset offset, ManagedRegister scratch) override; 186 void Call(FrameOffset base, Offset offset, ManagedRegister scratch) override; 187 void CallFromThread(ThreadOffset32 offset, ManagedRegister scratch) override; 188 189 // Generate code to check if Thread::Current()->exception_ is non-null 190 // and branch to a ExceptionSlowPath if it is. 191 void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) override; 192 193 // Create a new label that can be used with Jump/Bind calls. 194 std::unique_ptr<JNIMacroLabel> CreateLabel() override; 195 // Emit an unconditional jump to the label. 196 void Jump(JNIMacroLabel* label) override; 197 // Emit a conditional jump to the label by applying a unary condition test to the register. 198 void Jump(JNIMacroLabel* label, JNIMacroUnaryCondition cond, ManagedRegister test) override; 199 // Code at this offset will serve as the target for the Jump call. 200 void Bind(JNIMacroLabel* label) override; 201 202 void MemoryBarrier(ManagedRegister scratch) override; 203 204 void EmitExceptionPoll(ArmVIXLJNIMacroAssembler::ArmException *exception); 205 void Load(ArmManagedRegister dest, vixl32::Register base, int32_t offset, size_t size); 206 207 private: 208 class ArmException { 209 private: ArmException(ArmManagedRegister scratch,size_t stack_adjust)210 ArmException(ArmManagedRegister scratch, size_t stack_adjust) 211 : scratch_(scratch), stack_adjust_(stack_adjust) {} 212 Entry()213 vixl32::Label* Entry() { return &exception_entry_; } 214 215 // Register used for passing Thread::Current()->exception_ . 216 const ArmManagedRegister scratch_; 217 218 // Stack adjust for ExceptionPool. 219 const size_t stack_adjust_; 220 221 vixl32::Label exception_entry_; 222 223 friend class ArmVIXLJNIMacroAssembler; 224 DISALLOW_COPY_AND_ASSIGN(ArmException); 225 }; 226 227 // List of exception blocks to generate at the end of the code cache. 228 ArenaVector<std::unique_ptr<ArmVIXLJNIMacroAssembler::ArmException>> exception_blocks_; 229 // Used for testing. 230 friend class ArmVIXLAssemblerTest_VixlLoadFromOffset_Test; 231 friend class ArmVIXLAssemblerTest_VixlStoreToOffset_Test; 232 }; 233 234 class ArmVIXLJNIMacroLabel final 235 : public JNIMacroLabelCommon<ArmVIXLJNIMacroLabel, 236 vixl32::Label, 237 InstructionSet::kArm> { 238 public: AsArm()239 vixl32::Label* AsArm() { 240 return AsPlatformLabel(); 241 } 242 }; 243 244 } // namespace arm 245 } // namespace art 246 247 #endif // ART_COMPILER_UTILS_ARM_JNI_MACRO_ASSEMBLER_ARM_VIXL_H_ 248