v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
parallel-move.cc
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
6
8
9namespace v8::internal::wasm {
10
11void ParallelMove::TransferToStack(int dst_offset, const VarState& src) {
12 switch (src.loc()) {
14 // Same offsets can happen even if we move values down in the value stack,
15 // because of alignment.
16 if (src.offset() == dst_offset) return;
17#if DEBUG
18 // Check that the stack value at `dst_offset` is not used in a pending
19 // register load.
21 DCHECK(!reg.is_pair());
23 if (load->load_kind == RegisterLoad::kStack ||
24 load->load_kind == RegisterLoad::kLowHalfStack) {
25 // We overwrite the lower half of the stack value for sure.
26 DCHECK_NE(load->value, dst_offset);
27 } else if (load->load_kind == RegisterLoad::kHighHalfStack &&
28 value_kind_size(src.kind()) > kInt32Size) {
29 // We overwrite the full stack slot, but we still need the higher half
30 // later.
31 DCHECK_NE(load->value, dst_offset);
32 }
33 }
34#endif
35 asm_->MoveStackValue(dst_offset, src.offset(), src.kind());
36 break;
38 asm_->Spill(dst_offset, src.reg(), src.kind());
39 break;
41 asm_->Spill(dst_offset, src.constant());
42 break;
43 }
44}
45
47 // Execute all moves whose {dst} is not being used as src in another move.
48 // If any src count drops to zero, also (transitively) execute the
49 // corresponding move to that register.
51 // Check if already handled via transitivity in {ClearExecutedMove}.
52 if (!move_dst_regs_.has(dst)) continue;
53 if (*src_reg_use_count(dst)) continue;
54 ExecuteMove(dst);
55 }
56
57 // All remaining moves are parts of a cycle. Just spill the first one, then
58 // process all remaining moves in that cycle. Repeat for all cycles.
59 while (!move_dst_regs_.is_empty()) {
60 // TODO(clemensb): Use an unused register if available.
62 RegisterMove* move = register_move(dst);
64 LiftoffRegister spill_reg = move->src;
65 asm_->Spill(last_spill_offset_, spill_reg, move->kind);
66 // Remember to reload into the destination register later.
67 LoadStackSlot(dst, last_spill_offset_, move->kind);
69 }
70}
71
74 RegisterLoad* load = register_load(dst);
75 switch (load->load_kind) {
77 break;
79 asm_->LoadConstant(dst, load->kind == kI64
80 ? WasmValue(int64_t{load->value})
81 : WasmValue(int32_t{load->value}));
82 break;
84 if (kNeedS128RegPair && load->kind == kS128) {
85 asm_->Fill(LiftoffRegister::ForFpPair(dst.fp()), load->value,
86 load->kind);
87 } else {
88 asm_->Fill(dst, load->value, load->kind);
89 }
90 break;
92 // Half of a register pair, {dst} must be a gp register.
93 asm_->FillI64Half(dst.gp(), load->value, kLowWord);
94 break;
96 // Half of a register pair, {dst} must be a gp register.
97 asm_->FillI64Half(dst.gp(), load->value, kHighWord);
98 break;
99 }
100 }
101 load_dst_regs_ = {};
102}
103
104} // namespace v8::internal::wasm
void FillI64Half(Register, int offset, RegPairHalf)
void Fill(LiftoffRegister, int offset, ValueKind)
void LoadConstant(LiftoffRegister, WasmValue)
void MoveStackValue(uint32_t dst_offset, uint32_t src_offset, ValueKind)
bool has(LiftoffRegister reg) const
LiftoffRegister GetFirstRegSet() const
static LiftoffRegister ForFpPair(DoubleRegister low)
void ClearExecutedMove(LiftoffRegister dst)
RegisterLoad * register_load(LiftoffRegister reg)
LiftoffAssembler *const asm_
void TransferToStack(int dst_offset, const VarState &src)
void LoadStackSlot(LiftoffRegister dst, int stack_offset, ValueKind kind)
V8_NOINLINE V8_PRESERVE_MOST void ExecuteLoads()
void ExecuteMove(LiftoffRegister dst)
int * src_reg_use_count(LiftoffRegister reg)
RegisterMove * register_move(LiftoffRegister reg)
V8_NOINLINE V8_PRESERVE_MOST void ExecuteMoves()
LiftoffRegister reg
static constexpr bool kNeedS128RegPair
constexpr int value_kind_size(ValueKind kind)
constexpr int kInt32Size
Definition globals.h:401
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482