Commit 14faced4 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Fix moving stack values

On x64 the {kScratchRegister} cannot be held in a {LiftoffRegister},
since it is not a valid cache register. Also, the code unnecessarily
checked whether there is an unused cache register, but then didn't use
it. Simplify the logic to always use the scratch register, just
distinguish between 4-byte and 8-byte moves.
On ia32 we did not move 64-bit values correctly if we didn't have
unused registers and needed to move via the stack.

R=titzer@chromium.org

Bug: v8:6600, chromium:917588, chromium:917450
Change-Id: I0bbe946c6ac8fca62f85711ae47afdac9c02ae6b
Reviewed-on: https://chromium-review.googlesource.com/c/1391755Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58521}
parent 42a42a68
...@@ -134,6 +134,19 @@ inline Register GetTmpByteRegister(LiftoffAssembler* assm, Register candidate) { ...@@ -134,6 +134,19 @@ inline Register GetTmpByteRegister(LiftoffAssembler* assm, Register candidate) {
return assm->GetUnusedRegister(liftoff::kByteRegs).gp(); return assm->GetUnusedRegister(liftoff::kByteRegs).gp();
} }
inline void MoveStackValue(LiftoffAssembler* assm, const Operand& src,
const Operand& dst) {
if (assm->cache_state()->has_unused_register(kGpReg)) {
Register tmp = assm->cache_state()->unused_register(kGpReg).gp();
assm->mov(tmp, src);
assm->mov(dst, tmp);
} else {
// No free register, move via the stack.
assm->push(src);
assm->pop(dst);
}
}
constexpr DoubleRegister kScratchDoubleReg = xmm7; constexpr DoubleRegister kScratchDoubleReg = xmm7;
constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>" constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>"
...@@ -401,14 +414,16 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -401,14 +414,16 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index,
ValueType type) { ValueType type) {
DCHECK_NE(dst_index, src_index); if (needs_reg_pair(type)) {
if (cache_state_.has_unused_register(kGpReg)) { liftoff::MoveStackValue(this,
LiftoffRegister reg = GetUnusedRegister(kGpReg); liftoff::GetHalfStackSlot(src_index, kLowWord),
Fill(reg, src_index, type); liftoff::GetHalfStackSlot(dst_index, kLowWord));
Spill(dst_index, reg, type); liftoff::MoveStackValue(this,
liftoff::GetHalfStackSlot(src_index, kHighWord),
liftoff::GetHalfStackSlot(dst_index, kHighWord));
} else { } else {
push(liftoff::GetStackSlot(src_index)); liftoff::MoveStackValue(this, liftoff::GetStackSlot(src_index),
pop(liftoff::GetStackSlot(dst_index)); liftoff::GetStackSlot(dst_index));
} }
} }
......
...@@ -318,12 +318,15 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst, ...@@ -318,12 +318,15 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index, void LiftoffAssembler::MoveStackValue(uint32_t dst_index, uint32_t src_index,
ValueType type) { ValueType type) {
DCHECK_NE(dst_index, src_index); DCHECK_NE(dst_index, src_index);
if (cache_state_.has_unused_register(kGpReg)) { Operand src = liftoff::GetStackSlot(src_index);
Fill(LiftoffRegister{kScratchRegister}, src_index, type); Operand dst = liftoff::GetStackSlot(dst_index);
Spill(dst_index, LiftoffRegister{kScratchRegister}, type); if (ValueTypes::ElementSizeLog2Of(type) == 2) {
movl(kScratchRegister, src);
movl(dst, kScratchRegister);
} else { } else {
pushq(liftoff::GetStackSlot(src_index)); DCHECK_EQ(3, ValueTypes::ElementSizeLog2Of(type));
popq(liftoff::GetStackSlot(dst_index)); movq(kScratchRegister, src);
movq(dst, kScratchRegister);
} }
} }
......
// Copyright 2018 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.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig = builder.addType(makeSig([], [kWasmF64]));
builder.addFunction(undefined, sig)
.addLocals({f32_count: 5}).addLocals({f64_count: 3})
.addBody([
kExprBlock, kWasmF64,
kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
kExprI32Const, 0,
kExprIf, kWasmI32,
kExprI32Const, 0,
kExprElse,
kExprI32Const, 1,
kExprEnd,
kExprBrIf, 0,
kExprUnreachable,
kExprEnd
]);
builder.instantiate();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment