blob: 980de4139219c9685eab2d013544a0081d4585ca [file] [log] [blame]
Artem Serov12e097c2016-08-08 15:13:26 +01001/*
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
Andreas Gampe57943812017-12-06 21:39:13 -080020#include <android-base/logging.h>
21
Artem Serov12e097c2016-08-08 15:13:26 +010022#include "base/arena_containers.h"
Andreas Gampe57943812017-12-06 21:39:13 -080023#include "base/macros.h"
Artem Serov12e097c2016-08-08 15:13:26 +010024#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
32namespace art {
33namespace arm {
34
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010035class ArmVIXLJNIMacroAssembler final
Artem Serov12e097c2016-08-08 15:13:26 +010036 : public JNIMacroAssemblerFwd<ArmVIXLAssembler, PointerSize::k32> {
Artem Serov12e097c2016-08-08 15:13:26 +010037 public:
Vladimir Markoe764d2e2017-10-05 14:35:55 +010038 explicit ArmVIXLJNIMacroAssembler(ArenaAllocator* allocator)
Vladimir Markoc8c2bb62021-10-15 09:33:09 +010039 : JNIMacroAssemblerFwd(allocator) {}
Artem Serov12e097c2016-08-08 15:13:26 +010040
41 virtual ~ArmVIXLJNIMacroAssembler() {}
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010042 void FinalizeCode() override;
Artem Serov12e097c2016-08-08 15:13:26 +010043
44 //
45 // Overridden common assembler high-level functionality
46 //
47
48 // Emit code that will create an activation on the stack.
49 void BuildFrame(size_t frame_size,
50 ManagedRegister method_reg,
Vladimir Marko662f12e2020-02-26 12:46:09 +000051 ArrayRef<const ManagedRegister> callee_save_regs) override;
Artem Serov12e097c2016-08-08 15:13:26 +010052
53 // Emit code that will remove an activation from the stack.
54 void RemoveFrame(size_t frame_size,
Roland Levillain0d127e12017-07-05 17:01:11 +010055 ArrayRef<const ManagedRegister> callee_save_regs,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010056 bool may_suspend) override;
Artem Serov12e097c2016-08-08 15:13:26 +010057
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010058 void IncreaseFrameSize(size_t adjust) override;
59 void DecreaseFrameSize(size_t adjust) override;
Artem Serov12e097c2016-08-08 15:13:26 +010060
Vladimir Markod95a1f22021-03-23 16:32:52 +000061 ManagedRegister CoreRegisterWithSize(ManagedRegister src, size_t size) override;
62
Artem Serov12e097c2016-08-08 15:13:26 +010063 // Store routines.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010064 void Store(FrameOffset offs, ManagedRegister src, size_t size) override;
Vladimir Markod95a1f22021-03-23 16:32:52 +000065 void Store(ManagedRegister base, MemberOffset offs, ManagedRegister src, size_t size) override;
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010066 void StoreRef(FrameOffset dest, ManagedRegister src) override;
67 void StoreRawPtr(FrameOffset dest, ManagedRegister src) override;
Artem Serov12e097c2016-08-08 15:13:26 +010068
Vladimir Marko662f12e2020-02-26 12:46:09 +000069 void StoreImmediateToFrame(FrameOffset dest, uint32_t imm) override;
Artem Serov12e097c2016-08-08 15:13:26 +010070
Vladimir Marko662f12e2020-02-26 12:46:09 +000071 void StoreStackOffsetToThread(ThreadOffset32 thr_offs, FrameOffset fr_offs) override;
Artem Serov12e097c2016-08-08 15:13:26 +010072
Mythri Allec2632ac2022-05-13 14:37:52 +000073 void StoreStackPointerToThread(ThreadOffset32 thr_offs, bool tag_sp) override;
Artem Serov12e097c2016-08-08 15:13:26 +010074
Vladimir Marko662f12e2020-02-26 12:46:09 +000075 void StoreSpanning(FrameOffset dest, ManagedRegister src, FrameOffset in_off) override;
Artem Serov12e097c2016-08-08 15:13:26 +010076
77 // Load routines.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010078 void Load(ManagedRegister dest, FrameOffset src, size_t size) override;
Vladimir Markod95a1f22021-03-23 16:32:52 +000079 void Load(ManagedRegister dest, ManagedRegister base, MemberOffset offs, size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +010080
81 void LoadFromThread(ManagedRegister dest,
82 ThreadOffset32 src,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010083 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +010084
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010085 void LoadRef(ManagedRegister dest, FrameOffset src) override;
Artem Serov12e097c2016-08-08 15:13:26 +010086
87 void LoadRef(ManagedRegister dest,
88 ManagedRegister base,
89 MemberOffset offs,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010090 bool unpoison_reference) override;
Artem Serov12e097c2016-08-08 15:13:26 +010091
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010092 void LoadRawPtr(ManagedRegister dest, ManagedRegister base, Offset offs) override;
Artem Serov12e097c2016-08-08 15:13:26 +010093
Roland Levillainbbc6e7e2018-08-24 16:58:47 +010094 void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset32 offs) override;
Artem Serov12e097c2016-08-08 15:13:26 +010095
96 // Copying routines.
Vladimir Markod3aaf942021-11-02 10:51:57 +000097 void MoveArguments(ArrayRef<ArgumentLocation> dests,
98 ArrayRef<ArgumentLocation> srcs,
99 ArrayRef<FrameOffset> refs) override;
Vladimir Marko03008222020-03-06 14:04:21 +0000100
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100101 void Move(ManagedRegister dest, ManagedRegister src, size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100102
Vladimir Marko662f12e2020-02-26 12:46:09 +0000103 void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset32 thr_offs) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100104
105 void CopyRawPtrToThread(ThreadOffset32 thr_offs,
106 FrameOffset fr_offs,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100107 ManagedRegister scratch) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100108
Vladimir Marko662f12e2020-02-26 12:46:09 +0000109 void CopyRef(FrameOffset dest, FrameOffset src) override;
110 void CopyRef(FrameOffset dest,
111 ManagedRegister base,
112 MemberOffset offs,
113 bool unpoison_reference) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100114
Vladimir Marko662f12e2020-02-26 12:46:09 +0000115 void Copy(FrameOffset dest, FrameOffset src, size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100116
117 void Copy(FrameOffset dest,
118 ManagedRegister src_base,
119 Offset src_offset,
120 ManagedRegister scratch,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100121 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100122
123 void Copy(ManagedRegister dest_base,
124 Offset dest_offset,
125 FrameOffset src,
126 ManagedRegister scratch,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100127 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100128
129 void Copy(FrameOffset dest,
130 FrameOffset src_base,
131 Offset src_offset,
132 ManagedRegister scratch,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100133 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100134
135 void Copy(ManagedRegister dest,
136 Offset dest_offset,
137 ManagedRegister src,
138 Offset src_offset,
139 ManagedRegister scratch,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100140 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100141
142 void Copy(FrameOffset dest,
143 Offset dest_offset,
144 FrameOffset src,
145 Offset src_offset,
146 ManagedRegister scratch,
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100147 size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100148
149 // Sign extension.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100150 void SignExtend(ManagedRegister mreg, size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100151
152 // Zero extension.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100153 void ZeroExtend(ManagedRegister mreg, size_t size) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100154
155 // Exploit fast access in managed code to Thread::Current().
Vladimir Marko662f12e2020-02-26 12:46:09 +0000156 void GetCurrentThread(ManagedRegister dest) override;
157 void GetCurrentThread(FrameOffset dest_offset) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100158
Vladimir Markocedec9d2021-02-08 16:16:13 +0000159 // Set up `out_reg` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
160 // or to be null if the value is null and `null_allowed`. `in_reg` holds a possibly
161 // stale reference that can be used to avoid loading the spilled value to
162 // see if the value is null.
163 void CreateJObject(ManagedRegister out_reg,
164 FrameOffset spilled_reference_offset,
165 ManagedRegister in_reg,
166 bool null_allowed) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100167
Vladimir Markocedec9d2021-02-08 16:16:13 +0000168 // Set up `out_off` to hold a `jobject` (`StackReference<Object>*` to a spilled value),
169 // or to be null if the value is null and `null_allowed`.
170 void CreateJObject(FrameOffset out_off,
171 FrameOffset spilled_reference_offset,
172 bool null_allowed) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100173
174 // Heap::VerifyObject on src. In some cases (such as a reference to this) we
175 // know that src may not be null.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100176 void VerifyObject(ManagedRegister src, bool could_be_null) override;
177 void VerifyObject(FrameOffset src, bool could_be_null) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100178
Vladimir Marko1c3c1062019-12-03 11:18:44 +0000179 // Jump to address held at [base+offset] (used for tail calls).
Vladimir Marko662f12e2020-02-26 12:46:09 +0000180 void Jump(ManagedRegister base, Offset offset) override;
Vladimir Marko1c3c1062019-12-03 11:18:44 +0000181
Artem Serov12e097c2016-08-08 15:13:26 +0100182 // Call to address held at [base+offset].
Vladimir Marko662f12e2020-02-26 12:46:09 +0000183 void Call(ManagedRegister base, Offset offset) override;
Vladimir Marko662f12e2020-02-26 12:46:09 +0000184 void CallFromThread(ThreadOffset32 offset) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100185
Vladimir Markoce2a3442021-11-24 15:10:26 +0000186 // Generate fast-path for transition to Native. Go to `label` if any thread flag is set.
Vladimir Markoe74e0ce2021-12-08 14:16:21 +0000187 // The implementation can use `scratch_regs` which should be callee save core registers
188 // (already saved before this call) and must preserve all argument registers.
Vladimir Markoce2a3442021-11-24 15:10:26 +0000189 void TryToTransitionFromRunnableToNative(
190 JNIMacroLabel* label, ArrayRef<const ManagedRegister> scratch_regs) override;
191
Vladimir Markoe74e0ce2021-12-08 14:16:21 +0000192 // Generate fast-path for transition to Runnable. Go to `label` if any thread flag is set.
193 // The implementation can use `scratch_regs` which should be core argument registers
194 // not used as return registers and it must preserve the `return_reg` if any.
195 void TryToTransitionFromNativeToRunnable(JNIMacroLabel* label,
196 ArrayRef<const ManagedRegister> scratch_regs,
197 ManagedRegister return_reg) override;
198
Vladimir Marko46a89102021-10-21 13:05:46 +0000199 // Generate suspend check and branch to `label` if there is a pending suspend request.
200 void SuspendCheck(JNIMacroLabel* label) override;
201
Artem Serov12e097c2016-08-08 15:13:26 +0100202 // Generate code to check if Thread::Current()->exception_ is non-null
Vladimir Markoc8c2bb62021-10-15 09:33:09 +0100203 // and branch to the `label` if it is.
204 void ExceptionPoll(JNIMacroLabel* label) override;
205 // Deliver pending exception.
206 void DeliverPendingException() override;
Artem Serov12e097c2016-08-08 15:13:26 +0100207
Igor Murashkinae7ff922016-10-06 14:59:19 -0700208 // Create a new label that can be used with Jump/Bind calls.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100209 std::unique_ptr<JNIMacroLabel> CreateLabel() override;
Igor Murashkinae7ff922016-10-06 14:59:19 -0700210 // Emit an unconditional jump to the label.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100211 void Jump(JNIMacroLabel* label) override;
Vladimir Marko662f12e2020-02-26 12:46:09 +0000212 // Emit a conditional jump to the label by applying a unary condition test to the GC marking flag.
213 void TestGcMarking(JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
Vladimir Markoad333922021-11-02 10:51:57 +0000214 // Emit a conditional jump to the label by applying a unary condition test to object's mark bit.
215 void TestMarkBit(ManagedRegister ref, JNIMacroLabel* label, JNIMacroUnaryCondition cond) override;
Igor Murashkinae7ff922016-10-06 14:59:19 -0700216 // Code at this offset will serve as the target for the Jump call.
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100217 void Bind(JNIMacroLabel* label) override;
Igor Murashkinae7ff922016-10-06 14:59:19 -0700218
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100219 void MemoryBarrier(ManagedRegister scratch) override;
Artem Serov12e097c2016-08-08 15:13:26 +0100220
Artem Serov12e097c2016-08-08 15:13:26 +0100221 void Load(ArmManagedRegister dest, vixl32::Register base, int32_t offset, size_t size);
222
223 private:
Artem Serov12e097c2016-08-08 15:13:26 +0100224 // Used for testing.
Vladimir Marko0e851e22016-08-25 18:17:56 +0100225 friend class ArmVIXLAssemblerTest_VixlLoadFromOffset_Test;
226 friend class ArmVIXLAssemblerTest_VixlStoreToOffset_Test;
Artem Serov12e097c2016-08-08 15:13:26 +0100227};
228
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100229class ArmVIXLJNIMacroLabel final
Igor Murashkinae7ff922016-10-06 14:59:19 -0700230 : public JNIMacroLabelCommon<ArmVIXLJNIMacroLabel,
231 vixl32::Label,
Vladimir Marko33bff252017-11-01 14:35:42 +0000232 InstructionSet::kArm> {
Igor Murashkinae7ff922016-10-06 14:59:19 -0700233 public:
234 vixl32::Label* AsArm() {
235 return AsPlatformLabel();
236 }
237};
238
Artem Serov12e097c2016-08-08 15:13:26 +0100239} // namespace arm
240} // namespace art
241
242#endif // ART_COMPILER_UTILS_ARM_JNI_MACRO_ASSEMBLER_ARM_VIXL_H_