diff options
Diffstat (limited to 'deps/v8/src/compiler/x64/code-generator-x64.cc')
-rw-r--r-- | deps/v8/src/compiler/x64/code-generator-x64.cc | 319 |
1 files changed, 261 insertions, 58 deletions
diff --git a/deps/v8/src/compiler/x64/code-generator-x64.cc b/deps/v8/src/compiler/x64/code-generator-x64.cc index 3160734788..0f1e959adc 100644 --- a/deps/v8/src/compiler/x64/code-generator-x64.cc +++ b/deps/v8/src/compiler/x64/code-generator-x64.cc @@ -44,7 +44,8 @@ class X64OperandConverter : public InstructionOperandConverter { Operand ToOperand(InstructionOperand* op, int extra = 0) { DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); // The linkage computes where all spill slots are located. - FrameOffset offset = linkage()->GetFrameOffset(op->index(), frame(), extra); + FrameOffset offset = linkage()->GetFrameOffset( + AllocatedOperand::cast(op)->index(), frame(), extra); return Operand(offset.from_stack_pointer() ? rsp : rbp, offset.offset()); } @@ -142,37 +143,37 @@ bool HasImmediateInput(Instruction* instr, size_t index) { } -class OutOfLineLoadZero FINAL : public OutOfLineCode { +class OutOfLineLoadZero final : public OutOfLineCode { public: OutOfLineLoadZero(CodeGenerator* gen, Register result) : OutOfLineCode(gen), result_(result) {} - void Generate() FINAL { __ xorl(result_, result_); } + void Generate() final { __ xorl(result_, result_); } private: Register const result_; }; -class OutOfLineLoadNaN FINAL : public OutOfLineCode { +class OutOfLineLoadNaN final : public OutOfLineCode { public: OutOfLineLoadNaN(CodeGenerator* gen, XMMRegister result) : OutOfLineCode(gen), result_(result) {} - void Generate() FINAL { __ pcmpeqd(result_, result_); } + void Generate() final { __ pcmpeqd(result_, result_); } private: XMMRegister const result_; }; -class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { +class OutOfLineTruncateDoubleToI final : public OutOfLineCode { public: OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result, XMMRegister input) : OutOfLineCode(gen), result_(result), input_(input) {} - void Generate() FINAL { + void Generate() final { __ subp(rsp, Immediate(kDoubleSize)); __ movsd(MemOperand(rsp, 0), input_); __ SlowTruncateToI(result_, rsp, 0); @@ -265,7 +266,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { } while (0) -#define ASSEMBLE_DOUBLE_BINOP(asm_instr) \ +#define ASSEMBLE_SSE_BINOP(asm_instr) \ do { \ if (instr->InputAt(1)->IsDoubleRegister()) { \ __ asm_instr(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); \ @@ -275,7 +276,17 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { } while (0) -#define ASSEMBLE_AVX_DOUBLE_BINOP(asm_instr) \ +#define ASSEMBLE_SSE_UNOP(asm_instr) \ + do { \ + if (instr->InputAt(0)->IsDoubleRegister()) { \ + __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ + } else { \ + __ asm_instr(i.OutputDoubleRegister(), i.InputOperand(0)); \ + } \ + } while (0) + + +#define ASSEMBLE_AVX_BINOP(asm_instr) \ do { \ CpuFeatureScope avx_scope(masm(), AVX); \ if (instr->InputAt(1)->IsDoubleRegister()) { \ @@ -304,7 +315,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { auto length = i.InputInt32(3); \ DCHECK_LE(index2, length); \ __ cmpq(index1, Immediate(length - index2)); \ - class OutOfLineLoadFloat FINAL : public OutOfLineCode { \ + class OutOfLineLoadFloat final : public OutOfLineCode { \ public: \ OutOfLineLoadFloat(CodeGenerator* gen, XMMRegister result, \ Register buffer, Register index1, int32_t index2, \ @@ -316,7 +327,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { index2_(index2), \ length_(length) {} \ \ - void Generate() FINAL { \ + void Generate() final { \ __ leal(kScratchRegister, Operand(index1_, index2_)); \ __ pcmpeqd(result_, result_); \ __ cmpl(kScratchRegister, Immediate(length_)); \ @@ -357,7 +368,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { auto length = i.InputInt32(3); \ DCHECK_LE(index2, length); \ __ cmpq(index1, Immediate(length - index2)); \ - class OutOfLineLoadInteger FINAL : public OutOfLineCode { \ + class OutOfLineLoadInteger final : public OutOfLineCode { \ public: \ OutOfLineLoadInteger(CodeGenerator* gen, Register result, \ Register buffer, Register index1, int32_t index2, \ @@ -369,7 +380,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { index2_(index2), \ length_(length) {} \ \ - void Generate() FINAL { \ + void Generate() final { \ Label oob; \ __ leal(kScratchRegister, Operand(index1_, index2_)); \ __ cmpl(kScratchRegister, Immediate(length_)); \ @@ -415,7 +426,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { auto length = i.InputInt32(3); \ DCHECK_LE(index2, length); \ __ cmpq(index1, Immediate(length - index2)); \ - class OutOfLineStoreFloat FINAL : public OutOfLineCode { \ + class OutOfLineStoreFloat final : public OutOfLineCode { \ public: \ OutOfLineStoreFloat(CodeGenerator* gen, Register buffer, \ Register index1, int32_t index2, int32_t length, \ @@ -427,7 +438,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { length_(length), \ value_(value) {} \ \ - void Generate() FINAL { \ + void Generate() final { \ __ leal(kScratchRegister, Operand(index1_, index2_)); \ __ cmpl(kScratchRegister, Immediate(length_)); \ __ j(above_equal, exit()); \ @@ -468,7 +479,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { auto length = i.InputInt32(3); \ DCHECK_LE(index2, length); \ __ cmpq(index1, Immediate(length - index2)); \ - class OutOfLineStoreInteger FINAL : public OutOfLineCode { \ + class OutOfLineStoreInteger final : public OutOfLineCode { \ public: \ OutOfLineStoreInteger(CodeGenerator* gen, Register buffer, \ Register index1, int32_t index2, int32_t length, \ @@ -480,7 +491,7 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { length_(length), \ value_(value) {} \ \ - void Generate() FINAL { \ + void Generate() final { \ __ leal(kScratchRegister, Operand(index1_, index2_)); \ __ cmpl(kScratchRegister, Immediate(length_)); \ __ j(above_equal, exit()); \ @@ -516,6 +527,23 @@ class OutOfLineTruncateDoubleToI FINAL : public OutOfLineCode { } while (false) +void CodeGenerator::AssembleDeconstructActivationRecord() { + CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); + int stack_slots = frame()->GetSpillSlotCount(); + if (descriptor->IsJSFunctionCall() || stack_slots > 0) { + __ movq(rsp, rbp); + __ popq(rbp); + int32_t bytes_to_pop = + descriptor->IsJSFunctionCall() + ? static_cast<int32_t>(descriptor->JSParameterCount() * + kPointerSize) + : 0; + __ popq(Operand(rsp, bytes_to_pop)); + __ addq(rsp, Immediate(bytes_to_pop)); + } +} + + // Assembles an instruction after register allocation, producing machine code. void CodeGenerator::AssembleArchInstruction(Instruction* instr) { X64OperandConverter i(this, instr); @@ -534,6 +562,18 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { RecordCallPosition(instr); break; } + case kArchTailCallCodeObject: { + AssembleDeconstructActivationRecord(); + if (HasImmediateInput(instr, 0)) { + Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); + __ jmp(code, RelocInfo::CODE_TARGET); + } else { + Register reg = i.InputRegister(0); + int entry = Code::kHeaderSize - kHeapObjectTag; + __ jmp(Operand(reg, entry)); + } + break; + } case kArchCallJSFunction: { EnsureSpaceForLazyDeopt(); Register func = i.InputRegister(0); @@ -546,6 +586,17 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { RecordCallPosition(instr); break; } + case kArchTailCallJSFunction: { + Register func = i.InputRegister(0); + if (FLAG_debug_code) { + // Check the function's context matches the context argument. + __ cmpp(rsi, FieldOperand(func, JSFunction::kContextOffset)); + __ Assert(equal, kWrongFunctionContext); + } + AssembleDeconstructActivationRecord(); + __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); + break; + } case kArchJmp: AssembleArchJump(i.InputRpo(0)); break; @@ -701,20 +752,67 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ Lzcntl(i.OutputRegister(), i.InputOperand(0)); } break; + case kSSEFloat32Cmp: + ASSEMBLE_SSE_BINOP(ucomiss); + break; + case kSSEFloat32Add: + ASSEMBLE_SSE_BINOP(addss); + break; + case kSSEFloat32Sub: + ASSEMBLE_SSE_BINOP(subss); + break; + case kSSEFloat32Mul: + ASSEMBLE_SSE_BINOP(mulss); + break; + case kSSEFloat32Div: + ASSEMBLE_SSE_BINOP(divss); + // Don't delete this mov. It may improve performance on some CPUs, + // when there is a (v)mulss depending on the result. + __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); + break; + case kSSEFloat32Abs: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psrlq(kScratchDoubleReg, 33); + __ andps(i.OutputDoubleRegister(), kScratchDoubleReg); + break; + } + case kSSEFloat32Neg: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psllq(kScratchDoubleReg, 31); + __ xorps(i.OutputDoubleRegister(), kScratchDoubleReg); + break; + } + case kSSEFloat32Sqrt: + ASSEMBLE_SSE_UNOP(sqrtss); + break; + case kSSEFloat32Max: + ASSEMBLE_SSE_BINOP(maxss); + break; + case kSSEFloat32Min: + ASSEMBLE_SSE_BINOP(minss); + break; + case kSSEFloat32ToFloat64: + ASSEMBLE_SSE_UNOP(cvtss2sd); + break; case kSSEFloat64Cmp: - ASSEMBLE_DOUBLE_BINOP(ucomisd); + ASSEMBLE_SSE_BINOP(ucomisd); break; case kSSEFloat64Add: - ASSEMBLE_DOUBLE_BINOP(addsd); + ASSEMBLE_SSE_BINOP(addsd); break; case kSSEFloat64Sub: - ASSEMBLE_DOUBLE_BINOP(subsd); + ASSEMBLE_SSE_BINOP(subsd); break; case kSSEFloat64Mul: - ASSEMBLE_DOUBLE_BINOP(mulsd); + ASSEMBLE_SSE_BINOP(mulsd); break; case kSSEFloat64Div: - ASSEMBLE_DOUBLE_BINOP(divsd); + ASSEMBLE_SSE_BINOP(divsd); + // Don't delete this mov. It may improve performance on some CPUs, + // when there is a (v)mulsd depending on the result. + __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); break; case kSSEFloat64Mod: { __ subq(rsp, Immediate(kDoubleSize)); @@ -749,17 +847,27 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { break; } case kSSEFloat64Max: - ASSEMBLE_DOUBLE_BINOP(maxsd); + ASSEMBLE_SSE_BINOP(maxsd); break; case kSSEFloat64Min: - ASSEMBLE_DOUBLE_BINOP(minsd); + ASSEMBLE_SSE_BINOP(minsd); break; + case kSSEFloat64Abs: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psrlq(kScratchDoubleReg, 1); + __ andpd(i.OutputDoubleRegister(), kScratchDoubleReg); + break; + } + case kSSEFloat64Neg: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psllq(kScratchDoubleReg, 63); + __ xorpd(i.OutputDoubleRegister(), kScratchDoubleReg); + break; + } case kSSEFloat64Sqrt: - if (instr->InputAt(0)->IsDoubleRegister()) { - __ sqrtsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - } else { - __ sqrtsd(i.OutputDoubleRegister(), i.InputOperand(0)); - } + ASSEMBLE_SSE_UNOP(sqrtsd); break; case kSSEFloat64Round: { CpuFeatureScope sse_scope(masm(), SSE4_1); @@ -768,19 +876,8 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ roundsd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), mode); break; } - case kSSECvtss2sd: - if (instr->InputAt(0)->IsDoubleRegister()) { - __ cvtss2sd(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - } else { - __ cvtss2sd(i.OutputDoubleRegister(), i.InputOperand(0)); - } - break; - case kSSECvtsd2ss: - if (instr->InputAt(0)->IsDoubleRegister()) { - __ cvtsd2ss(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); - } else { - __ cvtsd2ss(i.OutputDoubleRegister(), i.InputOperand(0)); - } + case kSSEFloat64ToFloat32: + ASSEMBLE_SSE_UNOP(cvtsd2ss); break; case kSSEFloat64ToInt32: if (instr->InputAt(0)->IsDoubleRegister()) { @@ -848,24 +945,122 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ movd(i.OutputDoubleRegister(), i.InputOperand(0)); } break; + case kAVXFloat32Cmp: { + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(1)->IsDoubleRegister()) { + __ vucomiss(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); + } else { + __ vucomiss(i.InputDoubleRegister(0), i.InputOperand(1)); + } + break; + } + case kAVXFloat32Add: + ASSEMBLE_AVX_BINOP(vaddss); + break; + case kAVXFloat32Sub: + ASSEMBLE_AVX_BINOP(vsubss); + break; + case kAVXFloat32Mul: + ASSEMBLE_AVX_BINOP(vmulss); + break; + case kAVXFloat32Div: + ASSEMBLE_AVX_BINOP(vdivss); + // Don't delete this mov. It may improve performance on some CPUs, + // when there is a (v)mulss depending on the result. + __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); + break; + case kAVXFloat32Max: + ASSEMBLE_AVX_BINOP(vmaxss); + break; + case kAVXFloat32Min: + ASSEMBLE_AVX_BINOP(vminss); + break; + case kAVXFloat64Cmp: { + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(1)->IsDoubleRegister()) { + __ vucomisd(i.InputDoubleRegister(0), i.InputDoubleRegister(1)); + } else { + __ vucomisd(i.InputDoubleRegister(0), i.InputOperand(1)); + } + break; + } case kAVXFloat64Add: - ASSEMBLE_AVX_DOUBLE_BINOP(vaddsd); + ASSEMBLE_AVX_BINOP(vaddsd); break; case kAVXFloat64Sub: - ASSEMBLE_AVX_DOUBLE_BINOP(vsubsd); + ASSEMBLE_AVX_BINOP(vsubsd); break; case kAVXFloat64Mul: - ASSEMBLE_AVX_DOUBLE_BINOP(vmulsd); + ASSEMBLE_AVX_BINOP(vmulsd); break; case kAVXFloat64Div: - ASSEMBLE_AVX_DOUBLE_BINOP(vdivsd); + ASSEMBLE_AVX_BINOP(vdivsd); + // Don't delete this mov. It may improve performance on some CPUs, + // when there is a (v)mulsd depending on the result. + __ movaps(i.OutputDoubleRegister(), i.OutputDoubleRegister()); break; case kAVXFloat64Max: - ASSEMBLE_AVX_DOUBLE_BINOP(vmaxsd); + ASSEMBLE_AVX_BINOP(vmaxsd); break; case kAVXFloat64Min: - ASSEMBLE_AVX_DOUBLE_BINOP(vminsd); + ASSEMBLE_AVX_BINOP(vminsd); break; + case kAVXFloat32Abs: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psrlq(kScratchDoubleReg, 33); + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(0)->IsDoubleRegister()) { + __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputDoubleRegister(0)); + } else { + __ vandps(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputOperand(0)); + } + break; + } + case kAVXFloat32Neg: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psllq(kScratchDoubleReg, 31); + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(0)->IsDoubleRegister()) { + __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputDoubleRegister(0)); + } else { + __ vxorps(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputOperand(0)); + } + break; + } + case kAVXFloat64Abs: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psrlq(kScratchDoubleReg, 1); + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(0)->IsDoubleRegister()) { + __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputDoubleRegister(0)); + } else { + __ vandpd(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputOperand(0)); + } + break; + } + case kAVXFloat64Neg: { + // TODO(bmeurer): Use RIP relative 128-bit constants. + __ pcmpeqd(kScratchDoubleReg, kScratchDoubleReg); + __ psllq(kScratchDoubleReg, 63); + CpuFeatureScope avx_scope(masm(), AVX); + if (instr->InputAt(0)->IsDoubleRegister()) { + __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputDoubleRegister(0)); + } else { + __ vxorpd(i.OutputDoubleRegister(), kScratchDoubleReg, + i.InputOperand(0)); + } + break; + } case kX64Movsxbl: ASSEMBLE_MOVX(movsxbl); __ AssertZeroExtended(i.OutputRegister()); @@ -1014,13 +1209,20 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { break; case kX64StoreWriteBarrier: { Register object = i.InputRegister(0); - Register index = i.InputRegister(1); Register value = i.InputRegister(2); - __ movq(Operand(object, index, times_1, 0), value); - __ leaq(index, Operand(object, index, times_1, 0)); SaveFPRegsMode mode = frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; - __ RecordWrite(object, index, value, mode); + if (HasImmediateInput(instr, 1)) { + int index = i.InputInt32(1); + Register scratch = i.TempRegister(1); + __ movq(Operand(object, index), value); + __ RecordWriteContextSlot(object, index, value, scratch, mode); + } else { + Register index = i.InputRegister(1); + __ movq(Operand(object, index, times_1, 0), value); + __ leaq(index, Operand(object, index, times_1, 0)); + __ RecordWrite(object, index, value, mode); + } break; } case kCheckedLoadInt8: @@ -1308,7 +1510,7 @@ void CodeGenerator::AssembleReturn() { int pop_count = descriptor->IsJSFunctionCall() ? static_cast<int>(descriptor->JSParameterCount()) : 0; - __ ret(pop_count * kPointerSize); + __ Ret(pop_count * kPointerSize, rbx); } else { __ ret(0); } @@ -1369,11 +1571,12 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, break; case Constant::kHeapObject: { Handle<HeapObject> src_object = src.ToHeapObject(); - if (info()->IsOptimizing() && - src_object.is_identical_to(info()->context())) { - // Loading the context from the frame is way cheaper than - // materializing the actual context heap object address. - __ movp(dst, Operand(rbp, StandardFrameConstants::kContextOffset)); + Heap::RootListIndex index; + int offset; + if (IsMaterializableFromFrame(src_object, &offset)) { + __ movp(dst, Operand(rbp, offset)); + } else if (IsMaterializableFromRoot(src_object, &index)) { + __ LoadRoot(dst, index); } else { __ Move(dst, src_object); } |