v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
liftoff-assembler-inl.h
Go to the documentation of this file.
1// Copyright 2023 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_WASM_BASELINE_LIFTOFF_ASSEMBLER_INL_H_
6#define V8_WASM_BASELINE_LIFTOFF_ASSEMBLER_INL_H_
7
9// Include the non-inl header before the rest of the headers.
10
11// Include platform specific implementation.
12#if V8_TARGET_ARCH_IA32
14#elif V8_TARGET_ARCH_X64
16#elif V8_TARGET_ARCH_ARM64
18#elif V8_TARGET_ARCH_ARM
20#elif V8_TARGET_ARCH_PPC64
22#elif V8_TARGET_ARCH_MIPS64
24#elif V8_TARGET_ARCH_LOONG64
26#elif V8_TARGET_ARCH_S390X
28#elif V8_TARGET_ARCH_RISCV64
30#elif V8_TARGET_ARCH_RISCV32
32#else
33#error Unsupported architecture.
34#endif
35
36namespace v8::internal::wasm {
37
38// static
40 int offset = top_spill_offset + SlotSizeForType(kind);
41 if (NeedsAlignment(kind)) {
43 }
44 return offset;
45}
46
50
52 return cache_state_.stack_state.empty()
54 : cache_state_.stack_state.back().offset();
55}
56
62
63// Assumes that the exception is in {kReturnRegister0}. This is where the
64// exception is stored by the unwinder after a throwing call.
67 // This is used after a call, so {kReturnRegister0} is not used yet.
71}
72
74 V8_ASSUME(kind == kI32 || kind == kI64);
75 cache_state_.stack_state.emplace_back(kind, i32_const, NextSpillOffset(kind));
76}
77
81
83 DCHECK(slot.is_const() || slot.is_stack());
84 if (slot.is_const()) {
85 LoadConstant(reg, slot.constant());
86 } else {
87 Fill(reg, slot.offset(), slot.kind());
88 }
89}
90
93 VarState slot = cache_state_.stack_state.back();
94 cache_state_.stack_state.pop_back();
95 if (V8_LIKELY(slot.is_reg())) {
97 if (slot.reg() == reg) return;
99 Move(reg, slot.reg(), slot.kind());
100 return;
101 }
104}
105
112
114 int32_t offset) {
115 if constexpr (SmiValuesAre32Bits()) {
116#if V8_TARGET_LITTLE_ENDIAN
118 offset += 4;
119#endif
120 Load(dst, src_addr, no_reg, offset, LoadType::kI32Load);
121 } else {
123 Load(dst, src_addr, no_reg, offset, LoadType::kI32Load);
124 emit_i32_sari(dst.gp(), dst.gp(), kSmiTagSize);
125 }
126}
127
129 int32_t offset_imm) {
130 return Load(LiftoffRegister(dst), src_addr, no_reg, offset_imm,
131 LoadType::kI32Load);
132}
133
135 Register rhs) {
136 if constexpr (kSystemPointerSize == 8) {
138 LiftoffRegister(rhs));
139 } else {
140 emit_i32_add(dst, lhs, rhs);
141 }
142}
143
145 Register rhs) {
146 if constexpr (kSystemPointerSize == 8) {
148 LiftoffRegister(rhs));
149 } else {
150 emit_i32_sub(dst, lhs, rhs);
151 }
152}
153
155 Register rhs) {
156 if constexpr (kSystemPointerSize == 8) {
158 LiftoffRegister(rhs));
159 } else {
160 emit_i32_and(dst, lhs, rhs);
161 }
162}
163
165 int amount) {
166 if constexpr (kSystemPointerSize == 8) {
168 } else {
169 emit_i32_shri(dst, src, amount);
170 }
171}
172
174 intptr_t imm) {
175 if constexpr (kSystemPointerSize == 8) {
177 } else {
178 emit_i32_addi(dst, lhs, static_cast<int32_t>(imm));
179 }
180}
181
183 int32_t imm) {
184 if constexpr (kSystemPointerSize == 8) {
186 } else {
187 emit_i32_muli(dst, lhs, imm);
188 }
189}
190
192 LiftoffRegister lhs,
193 LiftoffRegister rhs) {
194 if constexpr (kSystemPointerSize == 8) {
195 emit_i64_set_cond(condition, dst, lhs, rhs);
196 } else {
197 emit_i32_set_cond(condition, dst, lhs.gp(), rhs.gp());
198 }
199}
200
202 const char* detail) {
203 DCHECK_NE(kSuccess, reason);
204 if (bailout_reason_ != kSuccess) return;
206 bailout_reason_ = reason;
207 bailout_detail_ = detail;
208}
209
210// =======================================================================
211// Partially platform-independent implementations of the platform-dependent
212// part.
213
214#ifdef V8_TARGET_ARCH_32_BIT
215
217 Register lhs, int32_t imm,
218 const FreezeCacheState& frozen) {
219 emit_i32_cond_jumpi(cond, label, lhs, imm, frozen);
220}
221
222namespace liftoff {
223template <void (LiftoffAssembler::*op)(Register, Register, Register)>
224void EmitI64IndependentHalfOperation(LiftoffAssembler* assm,
225 LiftoffRegister dst, LiftoffRegister lhs,
226 LiftoffRegister rhs) {
227 // If {dst.low_gp()} does not overlap with {lhs.high_gp()} or {rhs.high_gp()},
228 // just first compute the lower half, then the upper half.
229 if (dst.low() != lhs.high() && dst.low() != rhs.high()) {
230 (assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
231 (assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
232 return;
233 }
234 // If {dst.high_gp()} does not overlap with {lhs.low_gp()} or {rhs.low_gp()},
235 // we can compute this the other way around.
236 if (dst.high() != lhs.low() && dst.high() != rhs.low()) {
237 (assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
238 (assm->*op)(dst.low_gp(), lhs.low_gp(), rhs.low_gp());
239 return;
240 }
241 // Otherwise, we need a temporary register.
242 Register tmp = assm->GetUnusedRegister(kGpReg, LiftoffRegList{lhs, rhs}).gp();
243 (assm->*op)(tmp, lhs.low_gp(), rhs.low_gp());
244 (assm->*op)(dst.high_gp(), lhs.high_gp(), rhs.high_gp());
245 assm->Move(dst.low_gp(), tmp, kI32);
246}
247
248template <void (LiftoffAssembler::*op)(Register, Register, int32_t)>
249void EmitI64IndependentHalfOperationImm(LiftoffAssembler* assm,
250 LiftoffRegister dst,
251 LiftoffRegister lhs, int64_t imm) {
252 int32_t low_word = static_cast<int32_t>(imm);
253 int32_t high_word = static_cast<int32_t>(imm >> 32);
254 // If {dst.low_gp()} does not overlap with {lhs.high_gp()},
255 // just first compute the lower half, then the upper half.
256 if (dst.low() != lhs.high()) {
257 (assm->*op)(dst.low_gp(), lhs.low_gp(), low_word);
258 (assm->*op)(dst.high_gp(), lhs.high_gp(), high_word);
259 return;
260 }
261 // If {dst.high_gp()} does not overlap with {lhs.low_gp()},
262 // we can compute this the other way around.
263 if (dst.high() != lhs.low()) {
264 (assm->*op)(dst.high_gp(), lhs.high_gp(), high_word);
265 (assm->*op)(dst.low_gp(), lhs.low_gp(), low_word);
266 return;
267 }
268 // Otherwise, we need a temporary register.
269 Register tmp = assm->GetUnusedRegister(kGpReg, LiftoffRegList{lhs}).gp();
270 (assm->*op)(tmp, lhs.low_gp(), low_word);
271 (assm->*op)(dst.high_gp(), lhs.high_gp(), high_word);
272 assm->Move(dst.low_gp(), tmp, kI32);
273}
274} // namespace liftoff
275
276void LiftoffAssembler::emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs,
277 LiftoffRegister rhs) {
278 liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_and>(
279 this, dst, lhs, rhs);
280}
281
282void LiftoffAssembler::emit_i64_andi(LiftoffRegister dst, LiftoffRegister lhs,
283 int32_t imm) {
284 liftoff::EmitI64IndependentHalfOperationImm<&LiftoffAssembler::emit_i32_andi>(
285 this, dst, lhs, imm);
286}
287
288void LiftoffAssembler::emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs,
289 LiftoffRegister rhs) {
290 liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_or>(
291 this, dst, lhs, rhs);
292}
293
294void LiftoffAssembler::emit_i64_ori(LiftoffRegister dst, LiftoffRegister lhs,
295 int32_t imm) {
296 liftoff::EmitI64IndependentHalfOperationImm<&LiftoffAssembler::emit_i32_ori>(
297 this, dst, lhs, imm);
298}
299
300void LiftoffAssembler::emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs,
301 LiftoffRegister rhs) {
302 liftoff::EmitI64IndependentHalfOperation<&LiftoffAssembler::emit_i32_xor>(
303 this, dst, lhs, rhs);
304}
305
306void LiftoffAssembler::emit_i64_xori(LiftoffRegister dst, LiftoffRegister lhs,
307 int32_t imm) {
308 liftoff::EmitI64IndependentHalfOperationImm<&LiftoffAssembler::emit_i32_xori>(
309 this, dst, lhs, imm);
310}
311
312void LiftoffAssembler::emit_u32_to_uintptr(Register dst, Register src) {
313 if (dst != src) Move(dst, src, kI32);
314}
315
317
318#endif // V8_TARGET_ARCH_32_BIT
319
320// End of the partially platform-independent implementations of the
321// platform-dependent part.
322// =======================================================================
323
324} // namespace v8::internal::wasm
325
326#endif // V8_WASM_BASELINE_LIFTOFF_ASSEMBLER_INL_H_
Builtins::Kind kind
Definition builtins.cc:40
void emit_i64_ori(LiftoffRegister dst, LiftoffRegister lhs, int32_t imm)
void emit_i32_shri(Register dst, Register src, int32_t amount)
void emit_ptrsize_and(Register dst, Register lhs, Register rhs)
void emit_ptrsize_addi(Register dst, Register lhs, intptr_t imm)
void emit_i64_muli(LiftoffRegister dst, LiftoffRegister lhs, int32_t imm)
void emit_i64_xori(LiftoffRegister dst, LiftoffRegister lhs, int32_t imm)
void LoadFixedArrayLengthAsInt32(LiftoffRegister dst, Register array, LiftoffRegList pinned)
void Fill(LiftoffRegister, int offset, ValueKind)
void emit_ptrsize_muli(Register dst, Register lhs, int32_t imm)
void emit_i64_add(LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs)
void emit_ptrsize_set_cond(Condition condition, Register dst, LiftoffRegister lhs, LiftoffRegister rhs)
void Load(LiftoffRegister dst, Register src_addr, Register offset_reg, uintptr_t offset_imm, LoadType type, uint32_t *protected_load_pc=nullptr, bool is_load_mem=false, bool i64_offset=false, bool needs_shift=false)
static V8_INLINE int NextSpillOffset(ValueKind kind, int top_spill_offset)
void emit_ptrsize_add(Register dst, Register lhs, Register rhs)
void emit_i64_addi(LiftoffRegister dst, LiftoffRegister lhs, int64_t imm)
void emit_i32_and(Register dst, Register lhs, Register rhs)
void emit_ptrsize_shri(Register dst, Register src, int amount)
void emit_i32_sari(Register dst, Register src, int32_t amount)
void LoadConstant(LiftoffRegister, WasmValue)
void emit_ptrsize_sub(Register dst, Register lhs, Register rhs)
void emit_i64_xor(LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs)
void emit_u32_to_uintptr(Register dst, Register src)
void emit_i64_shri(LiftoffRegister dst, LiftoffRegister src, int32_t amount)
void emit_i64_set_cond(Condition condition, Register dst, LiftoffRegister lhs, LiftoffRegister rhs)
void LoadCodePointer(Register dst, Register src_addr, int32_t offset)
void Move(LiftoffRegister dst, LiftoffRegister src, ValueKind)
void emit_i64_sub(LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs)
void emit_ptrsize_cond_jumpi(Condition, Label *, Register lhs, int32_t imm, const FreezeCacheState &frozen)
void emit_i64_or(LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs)
void emit_i32_set_cond(Condition, Register dst, Register lhs, Register rhs)
void emit_i32_sub(Register dst, Register lhs, Register rhs)
void PopToFixedRegister(LiftoffRegister reg)
void PushRegister(ValueKind kind, LiftoffRegister reg)
void emit_i64_andi(LiftoffRegister dst, LiftoffRegister lhs, int32_t imm)
void LoadSmiAsInt32(LiftoffRegister dst, Register src_addr, int32_t offset)
void LoadToFixedRegister(VarState slot, LiftoffRegister reg)
void emit_i32_cond_jumpi(Condition, Label *, Register lhs, int imm, const FreezeCacheState &frozen)
void bailout(LiftoffBailoutReason reason, const char *detail)
void emit_i32_addi(Register dst, Register lhs, int32_t imm)
void PushConstant(ValueKind kind, int32_t i32_const)
void emit_i64_and(LiftoffRegister dst, LiftoffRegister lhs, LiftoffRegister rhs)
V8_NOINLINE V8_PRESERVE_MOST void SpillRegister(LiftoffRegister)
void emit_i32_add(Register dst, Register lhs, Register rhs)
void emit_i32_muli(Register dst, Register lhs, int32_t imm)
Label label
int32_t offset
LiftoffRegister reg
const int length_
Definition mul-fft.cc:473
int int32_t
Definition unicode.cc:40
static constexpr RegClass reg_class_for(ValueKind kind)
constexpr Register no_reg
constexpr int kBitsPerByte
Definition globals.h:682
const int kSmiTagSize
Definition v8-internal.h:87
constexpr int kSystemPointerSize
Definition globals.h:410
constexpr Register kReturnRegister0
constexpr bool SmiValuesAre31Bits()
const int kHeapObjectTag
Definition v8-internal.h:72
const int kSmiShiftSize
constexpr bool SmiValuesAre32Bits()
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
constexpr T RoundUp(T x, intptr_t m)
Definition macros.h:387
#define V8_ASSUME
Definition v8config.h:533
#define V8_LIKELY(condition)
Definition v8config.h:661