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