/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
deps/v8/src/wasm/baseline/parallel-move.cc
104 строки
4 KB
Michaël Zasso
deps: update V8 to 13.0.245.25
31 янв 2025, 14:45
Не верифицирован
31 янв 2025, 14:45
5edec0e
Код
Авторство
О чём код?
// Copyright 2023 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/wasm/baseline/parallel-move.h" #include "src/wasm/baseline/liftoff-assembler-inl.h" namespace v8::internal::wasm { void ParallelMove::TransferToStack(int dst_offset, const VarState& src) { switch (src.loc()) { case VarState::kStack: // Same offsets can happen even if we move values down in the value stack, // because of alignment. if (src.offset() == dst_offset) return; #if DEBUG // Check that the stack value at `dst_offset` is not used in a pending // register load. for (LiftoffRegister reg : load_dst_regs_) { DCHECK(!reg.is_pair()); RegisterLoad* load = register_load(reg); if (load->load_kind == RegisterLoad::kStack || load->load_kind == RegisterLoad::kLowHalfStack) { // We overwrite the lower half of the stack value for sure. DCHECK_NE(load->value, dst_offset); } else if (load->load_kind == RegisterLoad::kHighHalfStack && value_kind_size(src.kind()) > kInt32Size) { // We overwrite the full stack slot, but we still need the higher half // later. DCHECK_NE(load->value, dst_offset); } } #endif asm_->MoveStackValue(dst_offset, src.offset(), src.kind()); break; case VarState::kRegister: asm_->Spill(dst_offset, src.reg(), src.kind()); break; case VarState::kIntConst: asm_->Spill(dst_offset, src.constant()); break; } } void ParallelMove::ExecuteMoves() { // Execute all moves whose {dst} is not being used as src in another move. // If any src count drops to zero, also (transitively) execute the // corresponding move to that register. for (LiftoffRegister dst : move_dst_regs_) { // Check if already handled via transitivity in {ClearExecutedMove}. if (!move_dst_regs_.has(dst)) continue; if (*src_reg_use_count(dst)) continue; ExecuteMove(dst); } // All remaining moves are parts of a cycle. Just spill the first one, then // process all remaining moves in that cycle. Repeat for all cycles. while (!move_dst_regs_.is_empty()) { // TODO(clemensb): Use an unused register if available. LiftoffRegister dst = move_dst_regs_.GetFirstRegSet(); RegisterMove* move = register_move(dst); last_spill_offset_ += LiftoffAssembler::SlotSizeForType(move->kind); LiftoffRegister spill_reg = move->src; asm_->Spill(last_spill_offset_, spill_reg, move->kind); // Remember to reload into the destination register later. LoadStackSlot(dst, last_spill_offset_, move->kind); ClearExecutedMove(dst); } } void ParallelMove::ExecuteLoads() { for (LiftoffRegister dst : load_dst_regs_) { RegisterLoad* load = register_load(dst); switch (load->load_kind) { case RegisterLoad::kNop: break; case RegisterLoad::kConstant: asm_->LoadConstant(dst, load->kind == kI64 ? WasmValue(int64_t{load->value}) : WasmValue(int32_t{load->value})); break; case RegisterLoad::kStack: if (kNeedS128RegPair && load->kind == kS128) { asm_->Fill(LiftoffRegister::ForFpPair(dst.fp()), load->value, load->kind); } else { asm_->Fill(dst, load->value, load->kind); } break; case RegisterLoad::kLowHalfStack: // Half of a register pair, {dst} must be a gp register. asm_->FillI64Half(dst.gp(), load->value, kLowWord); break; case RegisterLoad::kHighHalfStack: // Half of a register pair, {dst} must be a gp register. asm_->FillI64Half(dst.gp(), load->value, kHighWord); break; } } load_dst_regs_ = {}; } } // namespace v8::internal::wasm