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