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
30namespace art {
31namespace arm {
32
33class ArmVIXLJNIMacroAssembler FINAL
34    : public JNIMacroAssemblerFwd<ArmVIXLAssembler, PointerSize::k32> {
35 private:
36  class ArmException;
37 public:
38  explicit ArmVIXLJNIMacroAssembler(ArenaAllocator* arena)
39      : JNIMacroAssemblerFwd(arena),
40        exception_blocks_(arena->Adapter(kArenaAllocAssembler)) {}
41
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:
207    ArmException(ArmManagedRegister scratch, size_t stack_adjust)
208        : scratch_(scratch), stack_adjust_(stack_adjust) {}
209
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
231class ArmVIXLJNIMacroLabel FINAL
232    : public JNIMacroLabelCommon<ArmVIXLJNIMacroLabel,
233                                 vixl32::Label,
234                                 kArm> {
235 public:
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