[stubs] Remove return register argument from DoubleToIStub

This changes DoubleToIStub to return its result on the stack instead
of a specific return register.

In a follow-up, the DoubleToIStub could be converted into a builtin.

Bug: v8:6666
Change-Id: I7852e1586c8f7b56bc5d2545a7bf6238dd2ad650
Reviewed-on: https://chromium-review.googlesource.com/1009702
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52587}
This commit is contained in:
jgruber 2018-04-12 17:14:56 +02:00 committed by Commit Bot
parent 3d468c3886
commit 87557649e4
23 changed files with 122 additions and 119 deletions

View File

@ -41,21 +41,24 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Label negate, done;
Register result_reg = destination();
UseScratchRegisterScope temps(masm);
Register result_reg = r7;
Register double_low = GetRegisterThatIsNotOneOf(result_reg);
Register double_high = GetRegisterThatIsNotOneOf(result_reg, double_low);
LowDwVfpRegister double_scratch = temps.AcquireLowD();
// Save the old values from these temporary registers on the stack.
__ Push(double_high, double_low);
__ Push(result_reg, double_high, double_low);
// Account for saved regs.
const int kArgumentOffset = 2 * kPointerSize;
const int kArgumentOffset = 3 * kPointerSize;
MemOperand input_operand(sp, kArgumentOffset);
MemOperand result_operand = input_operand;
// Load double input.
__ vldr(double_scratch, MemOperand(sp, kArgumentOffset));
__ vldr(double_scratch, input_operand);
__ vmov(double_low, double_high, double_scratch);
// Try to convert with a FPU convert instruction. This handles all
// non-saturating cases.
@ -122,9 +125,10 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ add(result_reg, result_reg, Operand(double_high, LSR, 31));
__ bind(&done);
__ str(result_reg, result_operand);
// Restore registers corrupted in this routine and return.
__ Pop(double_high, double_low);
__ Pop(result_reg, double_high, double_low);
__ Ret();
}

View File

@ -1658,7 +1658,8 @@ void TurboAssembler::TruncateDoubleToIDelayed(Zone* zone, Register result,
sub(sp, sp, Operand(kDoubleSize)); // Put input on stack.
vstr(double_input, MemOperand(sp, 0));
CallStubDelayed(new (zone) DoubleToIStub(nullptr, result));
CallStubDelayed(new (zone) DoubleToIStub(nullptr));
ldr(result, MemOperand(sp, 0));
add(sp, sp, Operand(kDoubleSize));
pop(lr);

View File

@ -39,7 +39,7 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Label done;
Register result = destination();
Register result = x7;
DCHECK(result.Is64Bits());
@ -48,7 +48,12 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
Register scratch2 = temps.AcquireX();
DoubleRegister double_scratch = temps.AcquireD();
__ Peek(double_scratch, 0);
// Account for saved regs.
const int kArgumentOffset = 2 * kPointerSize;
__ Push(result, scratch1); // scratch1 is also pushed to preserve alignment.
__ Peek(double_scratch, kArgumentOffset);
// Try to convert with a FPU convert instruction. This handles all
// non-saturating cases.
__ TryConvertDoubleToInt64(result, double_scratch, &done);
@ -93,6 +98,8 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ Lsl(result, mantissa, exponent);
__ Bind(&done);
__ Poke(result, kArgumentOffset);
__ Pop(scratch1, result);
__ Ret();
}

View File

@ -2319,9 +2319,10 @@ void TurboAssembler::TruncateDoubleToIDelayed(Zone* zone, Register result,
// If we fell through then inline version didn't succeed - call stub instead.
Push(lr, double_input);
auto stub = new (zone) DoubleToIStub(nullptr, result);
auto stub = new (zone) DoubleToIStub(nullptr);
// DoubleToIStub preserves any registers it needs to clobber.
CallStubDelayed(stub);
Ldr(result, MemOperand(sp, 0));
DCHECK_EQ(xzr.SizeInBytes(), double_input.SizeInBytes());
Pop(xzr, lr); // xzr to drop the double input on the stack.

View File

@ -733,25 +733,11 @@ enum EmbedMode {
class DoubleToIStub : public PlatformCodeStub {
public:
DoubleToIStub(Isolate* isolate, Register destination)
: PlatformCodeStub(isolate) {
minor_key_ = DestinationRegisterBits::encode(destination.code()) |
SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
}
explicit DoubleToIStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
bool SometimesSetsUpAFrame() override { return false; }
private:
Register destination() const {
return Register::from_code(DestinationRegisterBits::decode(minor_key_));
}
static const int kBitsPerRegisterNumber = 6;
STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
class DestinationRegisterBits
: public BitField<int, 0, kBitsPerRegisterNumber> {};
class SSE3Bits : public BitField<int, kBitsPerRegisterNumber, 1> {};
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
};

View File

@ -215,7 +215,8 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
void Generate() final {
__ sub(esp, Immediate(kDoubleSize));
__ movsd(MemOperand(esp, 0), input_);
__ SlowTruncateToIDelayed(zone_, result_);
__ SlowTruncateToIDelayed(zone_);
__ mov(result_, MemOperand(esp, 0));
__ add(esp, Immediate(kDoubleSize));
}

View File

@ -200,7 +200,8 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode {
unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(),
kDoubleSize);
__ Movsd(MemOperand(rsp, 0), input_);
__ SlowTruncateToIDelayed(zone_, result_);
__ SlowTruncateToIDelayed(zone_);
__ movl(result_, MemOperand(rsp, 0));
__ addp(rsp, Immediate(kDoubleSize));
unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(),
-kDoubleSize);

View File

@ -36,32 +36,28 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Register final_result_reg = this->destination();
Label check_negative, process_64_bits, done;
// Account for return address and saved regs.
const int kArgumentOffset = 3 * kPointerSize;
const int kArgumentOffset = 4 * kPointerSize;
MemOperand mantissa_operand(MemOperand(esp, kArgumentOffset));
MemOperand exponent_operand(
MemOperand(esp, kArgumentOffset + kDoubleSize / 2));
Register scratch1 = no_reg;
{
Register scratch_candidates[3] = { ebx, edx, edi };
for (int i = 0; i < 3; i++) {
scratch1 = scratch_candidates[i];
if (final_result_reg != scratch1) break;
}
}
// The result is returned on the stack.
MemOperand return_operand = mantissa_operand;
Register scratch1 = ebx;
// Since we must use ecx for shifts below, use some other register (eax)
// to calculate the result if ecx is the requested return register.
Register result_reg = final_result_reg == ecx ? eax : final_result_reg;
// to calculate the result.
Register result_reg = eax;
// Save ecx if it isn't the return register and therefore volatile, or if it
// is the return register, then save the temp register we use in its stead for
// the result.
Register save_reg = final_result_reg == ecx ? eax : ecx;
Register save_reg = eax;
__ push(ecx);
__ push(scratch1);
__ push(save_reg);
@ -125,12 +121,10 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
// Restore registers
__ bind(&done);
if (final_result_reg != result_reg) {
DCHECK(final_result_reg == ecx);
__ mov(final_result_reg, result_reg);
}
__ mov(return_operand, result_reg);
__ pop(save_reg);
__ pop(scratch1);
__ pop(ecx);
__ ret(0);
}

View File

@ -177,8 +177,8 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1,
return bytes;
}
void TurboAssembler::SlowTruncateToIDelayed(Zone* zone, Register result_reg) {
CallStubDelayed(new (zone) DoubleToIStub(nullptr, result_reg));
void TurboAssembler::SlowTruncateToIDelayed(Zone* zone) {
CallStubDelayed(new (zone) DoubleToIStub(nullptr));
}
void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,

View File

@ -299,7 +299,7 @@ class TurboAssembler : public Assembler {
void Cvtui2ss(XMMRegister dst, Register src, Register tmp);
void SlowTruncateToIDelayed(Zone* zone, Register result_reg);
void SlowTruncateToIDelayed(Zone* zone);
void Push(Register src) { push(src); }
void Push(Operand src) { push(src); }

View File

@ -38,7 +38,7 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Label out_of_range, only_low, negate, done;
Register result_reg = destination();
Register result_reg = t0;
Register scratch = GetRegisterThatIsNotOneOf(result_reg);
Register scratch2 = GetRegisterThatIsNotOneOf(result_reg, scratch);
@ -46,8 +46,9 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
DoubleRegister double_scratch = kLithiumScratchDouble;
// Account for saved regs.
const int kArgumentOffset = 3 * kPointerSize;
const int kArgumentOffset = 4 * kPointerSize;
__ Push(result_reg);
__ Push(scratch, scratch2, scratch3);
// Load double input.
@ -161,8 +162,9 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ Movz(result_reg, input_high, scratch);
__ bind(&done);
__ sw(result_reg, MemOperand(sp, kArgumentOffset));
__ Pop(scratch, scratch2, scratch3);
__ Pop(result_reg);
__ Ret();
}

View File

@ -2662,7 +2662,8 @@ void TurboAssembler::TruncateDoubleToIDelayed(Zone* zone, Register result,
Subu(sp, sp, Operand(kDoubleSize)); // Put input on stack.
Sdc1(double_input, MemOperand(sp, 0));
CallStubDelayed(new (zone) DoubleToIStub(nullptr, result));
CallStubDelayed(new (zone) DoubleToIStub(nullptr));
lw(result, MemOperand(sp, 0));
Addu(sp, sp, Operand(kDoubleSize));
pop(ra);

View File

@ -37,7 +37,7 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Label out_of_range, only_low, negate, done;
Register result_reg = destination();
Register result_reg = t0;
Register scratch = GetRegisterThatIsNotOneOf(result_reg);
Register scratch2 = GetRegisterThatIsNotOneOf(result_reg, scratch);
@ -45,8 +45,9 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
DoubleRegister double_scratch = kLithiumScratchDouble;
// Account for saved regs.
const int kArgumentOffset = 3 * kPointerSize;
const int kArgumentOffset = 4 * kPointerSize;
__ Push(result_reg);
__ Push(scratch, scratch2, scratch3);
// Load double input.
@ -161,7 +162,9 @@ void DoubleToIStub::Generate(MacroAssembler* masm) {
__ bind(&done);
__ Sd(result_reg, MemOperand(sp, kArgumentOffset));
__ Pop(scratch, scratch2, scratch3);
__ Pop(result_reg);
__ Ret();
}

View File

@ -3178,7 +3178,8 @@ void TurboAssembler::TruncateDoubleToIDelayed(Zone* zone, Register result,
Dsubu(sp, sp, Operand(kDoubleSize)); // Put input on stack.
Sdc1(double_input, MemOperand(sp, 0));
CallStubDelayed(new (zone) DoubleToIStub(nullptr, result));
CallStubDelayed(new (zone) DoubleToIStub(nullptr));
Ld(result, MemOperand(sp, 0));
Daddu(sp, sp, Operand(kDoubleSize));
pop(ra);

View File

@ -38,73 +38,68 @@ void ArrayNArgumentsConstructorStub::Generate(MacroAssembler* masm) {
void DoubleToIStub::Generate(MacroAssembler* masm) {
Register final_result_reg = this->destination();
Label check_negative, process_64_bits, done;
Label check_negative, process_64_bits, done;
// Account for return address and saved regs.
const int kArgumentOffset = 4 * kRegisterSize;
// Account for return address and saved regs.
const int kArgumentOffset = 3 * kRegisterSize;
MemOperand mantissa_operand(MemOperand(rsp, kArgumentOffset));
MemOperand exponent_operand(
MemOperand(rsp, kArgumentOffset + kDoubleSize / 2));
MemOperand mantissa_operand(MemOperand(rsp, kArgumentOffset));
MemOperand exponent_operand(
MemOperand(rsp, kArgumentOffset + kDoubleSize / 2));
// The result is returned on the stack.
MemOperand return_operand = mantissa_operand;
Register scratch1 = no_reg;
Register scratch_candidates[3] = { rbx, rdx, rdi };
for (int i = 0; i < 3; i++) {
scratch1 = scratch_candidates[i];
if (final_result_reg != scratch1) break;
}
Register scratch1 = rbx;
// Since we must use rcx for shifts below, use some other register (rax)
// to calculate the result if ecx is the requested return register.
Register result_reg = final_result_reg == rcx ? rax : final_result_reg;
// Save ecx if it isn't the return register and therefore volatile, or if it
// is the return register, then save the temp register we use in its stead
// for the result.
Register save_reg = final_result_reg == rcx ? rax : rcx;
__ pushq(scratch1);
__ pushq(save_reg);
// Since we must use rcx for shifts below, use some other register (rax)
// to calculate the result if ecx is the requested return register.
Register result_reg = rax;
// Save ecx if it isn't the return register and therefore volatile, or if it
// is the return register, then save the temp register we use in its stead
// for the result.
Register save_reg = rax;
__ pushq(rcx);
__ pushq(scratch1);
__ pushq(save_reg);
__ movl(scratch1, mantissa_operand);
__ Movsd(kScratchDoubleReg, mantissa_operand);
__ movl(rcx, exponent_operand);
__ movl(scratch1, mantissa_operand);
__ Movsd(kScratchDoubleReg, mantissa_operand);
__ movl(rcx, exponent_operand);
__ andl(rcx, Immediate(HeapNumber::kExponentMask));
__ shrl(rcx, Immediate(HeapNumber::kExponentShift));
__ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias));
__ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits));
__ j(below, &process_64_bits);
__ andl(rcx, Immediate(HeapNumber::kExponentMask));
__ shrl(rcx, Immediate(HeapNumber::kExponentShift));
__ leal(result_reg, MemOperand(rcx, -HeapNumber::kExponentBias));
__ cmpl(result_reg, Immediate(HeapNumber::kMantissaBits));
__ j(below, &process_64_bits);
// Result is entirely in lower 32-bits of mantissa
int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
__ subl(rcx, Immediate(delta));
__ xorl(result_reg, result_reg);
__ cmpl(rcx, Immediate(31));
__ j(above, &done);
__ shll_cl(scratch1);
__ jmp(&check_negative);
// Result is entirely in lower 32-bits of mantissa
int delta = HeapNumber::kExponentBias + Double::kPhysicalSignificandSize;
__ subl(rcx, Immediate(delta));
__ xorl(result_reg, result_reg);
__ cmpl(rcx, Immediate(31));
__ j(above, &done);
__ shll_cl(scratch1);
__ jmp(&check_negative);
__ bind(&process_64_bits);
__ Cvttsd2siq(result_reg, kScratchDoubleReg);
__ jmp(&done, Label::kNear);
__ bind(&process_64_bits);
__ Cvttsd2siq(result_reg, kScratchDoubleReg);
__ jmp(&done, Label::kNear);
// If the double was negative, negate the integer result.
__ bind(&check_negative);
__ movl(result_reg, scratch1);
__ negl(result_reg);
__ cmpl(exponent_operand, Immediate(0));
__ cmovl(greater, result_reg, scratch1);
// If the double was negative, negate the integer result.
__ bind(&check_negative);
__ movl(result_reg, scratch1);
__ negl(result_reg);
__ cmpl(exponent_operand, Immediate(0));
__ cmovl(greater, result_reg, scratch1);
// Restore registers
__ bind(&done);
if (final_result_reg != result_reg) {
DCHECK(final_result_reg == rcx);
__ movl(final_result_reg, result_reg);
}
__ popq(save_reg);
__ popq(scratch1);
__ ret(0);
// Restore registers
__ bind(&done);
__ movl(return_operand, result_reg);
__ popq(save_reg);
__ popq(scratch1);
__ popq(rcx);
__ ret(0);
}
void MathPowStub::Generate(MacroAssembler* masm) {

View File

@ -1765,8 +1765,8 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
}
void TurboAssembler::SlowTruncateToIDelayed(Zone* zone, Register result_reg) {
CallStubDelayed(new (zone) DoubleToIStub(nullptr, result_reg));
void TurboAssembler::SlowTruncateToIDelayed(Zone* zone) {
CallStubDelayed(new (zone) DoubleToIStub(nullptr));
}
void MacroAssembler::DoubleToI(Register result_reg, XMMRegister input_reg,

View File

@ -458,7 +458,7 @@ class TurboAssembler : public Assembler {
// HeapObjectRequest that will be fulfilled after code assembly.
void CallStubDelayed(CodeStub* stub);
void SlowTruncateToIDelayed(Zone* zone, Register result_reg);
void SlowTruncateToIDelayed(Zone* zone);
// Call a runtime routine.
void CallRuntimeDelayed(Zone* zone, Runtime::FunctionId fid,

View File

@ -52,7 +52,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
@ -88,6 +88,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub
__ Call(start, RelocInfo::EXTERNAL_REFERENCE);
__ ldr(destination_reg, MemOperand(sp, 0));
__ add(sp, sp, Operand(kDoubleSize));
// Make sure no registers have been unexpectedly clobbered

View File

@ -53,7 +53,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
@ -79,6 +79,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub.
__ Call(start, RelocInfo::EXTERNAL_REFERENCE);
__ Peek(destination_reg, 0);
__ Drop(2, kDoubleSize);

View File

@ -53,7 +53,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
__ push(ebx);
@ -81,6 +81,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub
__ call(start, RelocInfo::EXTERNAL_REFERENCE);
__ mov(destination_reg, MemOperand(esp, 0));
__ add(esp, Immediate(kDoubleSize));

View File

@ -54,7 +54,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
@ -93,6 +93,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub
__ Call(start, RelocInfo::EXTERNAL_REFERENCE);
__ lw(destination_reg, MemOperand(sp, 0));
__ Addu(sp, sp, Operand(kDoubleSize));

View File

@ -54,7 +54,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
@ -92,6 +92,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub
__ Call(start, RelocInfo::EXTERNAL_REFERENCE);
__ Ld(destination_reg, MemOperand(sp, 0));
__ Daddu(sp, sp, Operand(kDoubleSize));

View File

@ -53,7 +53,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
MacroAssembler masm(isolate, buffer, static_cast<int>(allocated),
v8::internal::CodeObjectRequired::kYes);
DoubleToIStub stub(isolate, destination_reg);
DoubleToIStub stub(isolate);
byte* start = stub.GetCode()->raw_instruction_start();
__ pushq(rbx);
@ -80,6 +80,7 @@ ConvertDToIFunc MakeConvertDToIFuncTrampoline(Isolate* isolate,
// Call through to the actual stub
__ Call(start, RelocInfo::EXTERNAL_REFERENCE);
__ movl(destination_reg, MemOperand(rsp, 0));
__ addq(rsp, Immediate(kDoubleSize));