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 | 158 |
1 files changed, 90 insertions, 68 deletions
diff --git a/deps/v8/src/compiler/x64/code-generator-x64.cc b/deps/v8/src/compiler/x64/code-generator-x64.cc index 5d7534d2eb..548e3eb416 100644 --- a/deps/v8/src/compiler/x64/code-generator-x64.cc +++ b/deps/v8/src/compiler/x64/code-generator-x64.cc @@ -187,11 +187,12 @@ class OutOfLineLoadFloat64NaN final : public OutOfLineCode { class OutOfLineTruncateDoubleToI final : public OutOfLineCode { public: OutOfLineTruncateDoubleToI(CodeGenerator* gen, Register result, - XMMRegister input, + XMMRegister input, StubCallMode stub_mode, UnwindingInfoWriter* unwinding_info_writer) : OutOfLineCode(gen), result_(result), input_(input), + stub_mode_(stub_mode), unwinding_info_writer_(unwinding_info_writer), isolate_(gen->isolate()), zone_(gen->zone()) {} @@ -201,7 +202,13 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode { unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(), kDoubleSize); __ Movsd(MemOperand(rsp, 0), input_); - __ Call(BUILTIN_CODE(isolate_, DoubleToI), RelocInfo::CODE_TARGET); + if (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) { + // A direct call to a wasm runtime stub defined in this module. + // Just encode the stub index. This will be patched at relocation. + __ near_call(wasm::WasmCode::kDoubleToI, RelocInfo::WASM_STUB_CALL); + } else { + __ Call(BUILTIN_CODE(isolate_, DoubleToI), RelocInfo::CODE_TARGET); + } __ movl(result_, MemOperand(rsp, 0)); __ addp(rsp, Immediate(kDoubleSize)); unwinding_info_writer_->MaybeIncreaseBaseOffsetAt(__ pc_offset(), @@ -211,6 +218,7 @@ class OutOfLineTruncateDoubleToI final : public OutOfLineCode { private: Register const result_; XMMRegister const input_; + StubCallMode stub_mode_; UnwindingInfoWriter* const unwinding_info_writer_; Isolate* isolate_; Zone* zone_; @@ -262,37 +270,23 @@ class OutOfLineRecordWrite final : public OutOfLineCode { class WasmOutOfLineTrap : public OutOfLineCode { public: - WasmOutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) - : OutOfLineCode(gen), - gen_(gen), - frame_elided_(frame_elided), - instr_(instr) {} + WasmOutOfLineTrap(CodeGenerator* gen, Instruction* instr) + : OutOfLineCode(gen), gen_(gen), instr_(instr) {} void Generate() override { X64OperandConverter i(gen_, instr_); - - Builtins::Name trap_id = - static_cast<Builtins::Name>(i.InputInt32(instr_->InputCount() - 1)); + TrapId trap_id = + static_cast<TrapId>(i.InputInt32(instr_->InputCount() - 1)); GenerateWithTrapId(trap_id); } protected: CodeGenerator* gen_; - void GenerateWithTrapId(Builtins::Name trap_id) { - bool old_has_frame = __ has_frame(); - if (frame_elided_) { - __ set_has_frame(true); - __ EnterFrame(StackFrame::WASM_COMPILED); - } - GenerateCallToTrap(trap_id); - if (frame_elided_) { - __ set_has_frame(old_has_frame); - } - } + void GenerateWithTrapId(TrapId trap_id) { GenerateCallToTrap(trap_id); } private: - void GenerateCallToTrap(Builtins::Name trap_id) { + void GenerateCallToTrap(TrapId trap_id) { if (!gen_->wasm_runtime_exception_support()) { // We cannot test calls to the runtime in cctest/test-run-wasm. // Therefore we emit a call to C here instead of a call to the runtime. @@ -306,8 +300,9 @@ class WasmOutOfLineTrap : public OutOfLineCode { __ Ret(static_cast<int>(pop_size), rcx); } else { gen_->AssembleSourcePosition(instr_); - __ Call(__ isolate()->builtins()->builtin_handle(trap_id), - RelocInfo::CODE_TARGET); + // A direct call to a wasm runtime stub defined in this module. + // Just encode the stub index. This will be patched at relocation. + __ near_call(static_cast<Address>(trap_id), RelocInfo::WASM_STUB_CALL); ReferenceMap* reference_map = new (gen_->zone()) ReferenceMap(gen_->zone()); gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, @@ -316,20 +311,17 @@ class WasmOutOfLineTrap : public OutOfLineCode { } } - bool frame_elided_; Instruction* instr_; }; class WasmProtectedInstructionTrap final : public WasmOutOfLineTrap { public: - WasmProtectedInstructionTrap(CodeGenerator* gen, int pc, bool frame_elided, - Instruction* instr) - : WasmOutOfLineTrap(gen, frame_elided, instr), pc_(pc) {} + WasmProtectedInstructionTrap(CodeGenerator* gen, int pc, Instruction* instr) + : WasmOutOfLineTrap(gen, instr), pc_(pc) {} void Generate() final { gen_->AddProtectedInstructionLanding(pc_, __ pc_offset()); - - GenerateWithTrapId(Builtins::kThrowWasmTrapMemOutOfBounds); + GenerateWithTrapId(TrapId::kTrapMemOutOfBounds); } private: @@ -342,8 +334,7 @@ void EmitOOLTrapIfNeeded(Zone* zone, CodeGenerator* codegen, const MemoryAccessMode access_mode = static_cast<MemoryAccessMode>(MiscField::decode(opcode)); if (access_mode == kMemoryAccessProtected) { - const bool frame_elided = !codegen->frame_access_state()->has_frame(); - new (zone) WasmProtectedInstructionTrap(codegen, pc, frame_elided, instr); + new (zone) WasmProtectedInstructionTrap(codegen, pc, instr); } } @@ -563,9 +554,8 @@ void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, // Load arguments count from current arguments adaptor frame (note, it // does not include receiver). Register caller_args_count_reg = scratch1; - __ SmiToInteger32( - caller_args_count_reg, - Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ SmiUntag(caller_args_count_reg, + Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); ParameterCount callee_args_count(args_reg); __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, @@ -691,6 +681,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ Call(code, RelocInfo::CODE_TARGET); } else { Register reg = i.InputRegister(0); + DCHECK_IMPLIES( + HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister), + reg == kJavaScriptCallCodeStartRegister); __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { __ RetpolineCall(reg); @@ -704,15 +697,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( } case kArchCallWasmFunction: { if (HasImmediateInput(instr, 0)) { - Address wasm_code = - static_cast<Address>(i.ToConstant(instr->InputAt(0)).ToInt64()); - if (info()->IsWasm()) { - __ near_call(wasm_code, RelocInfo::WASM_CALL); + Constant constant = i.ToConstant(instr->InputAt(0)); + Address wasm_code = static_cast<Address>(constant.ToInt64()); + if (DetermineStubCallMode() == StubCallMode::kCallWasmRuntimeStub) { + __ near_call(wasm_code, constant.rmode()); } else { if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { - __ RetpolineCall(wasm_code, RelocInfo::JS_TO_WASM_CALL); + __ RetpolineCall(wasm_code, constant.rmode()); } else { - __ Call(wasm_code, RelocInfo::JS_TO_WASM_CALL); + __ Call(wasm_code, constant.rmode()); } } } else { @@ -736,9 +729,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( } if (HasImmediateInput(instr, 0)) { Handle<Code> code = i.InputCode(0); - __ jmp(code, RelocInfo::CODE_TARGET); + __ Jump(code, RelocInfo::CODE_TARGET); } else { Register reg = i.InputRegister(0); + DCHECK_IMPLIES( + HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister), + reg == kJavaScriptCallCodeStartRegister); __ addp(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { __ RetpolineJump(reg); @@ -753,12 +749,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( } case kArchTailCallWasm: { if (HasImmediateInput(instr, 0)) { - Address wasm_code = - static_cast<Address>(i.ToConstant(instr->InputAt(0)).ToInt64()); - if (info()->IsWasm()) { - __ near_jmp(wasm_code, RelocInfo::WASM_CALL); + Constant constant = i.ToConstant(instr->InputAt(0)); + Address wasm_code = static_cast<Address>(constant.ToInt64()); + if (DetermineStubCallMode() == StubCallMode::kCallWasmRuntimeStub) { + __ near_jmp(wasm_code, constant.rmode()); } else { - __ Move(kScratchRegister, wasm_code, RelocInfo::JS_TO_WASM_CALL); + __ Move(kScratchRegister, wasm_code, constant.rmode()); __ jmp(kScratchRegister); } } else { @@ -777,10 +773,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kArchTailCallAddress: { CHECK(!HasImmediateInput(instr, 0)); Register reg = i.InputRegister(0); - if (HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister)) { - static_assert(kJavaScriptCallCodeStartRegister == rcx, "ABI mismatch"); - DCHECK_EQ(rcx, reg); - } + DCHECK_IMPLIES( + HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister), + reg == kJavaScriptCallCodeStartRegister); if (HasCallDescriptorFlag(instr, CallDescriptor::kRetpoline)) { __ RetpolineJump(reg); } else { @@ -873,6 +868,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kArchJmp: AssembleArchJump(i.InputRpo(0)); break; + case kArchBinarySearchSwitch: + AssembleArchBinarySearchSwitch(instr); + break; case kArchLookupSwitch: AssembleArchLookupSwitch(instr); break; @@ -931,14 +929,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ movq(i.OutputRegister(), rbp); } break; - case kArchRootsPointer: - __ movq(i.OutputRegister(), kRootRegister); - break; case kArchTruncateDoubleToI: { auto result = i.OutputRegister(); auto input = i.InputDoubleRegister(0); auto ool = new (zone()) OutOfLineTruncateDoubleToI( - this, result, input, &unwinding_info_writer_); + this, result, input, DetermineStubCallMode(), + &unwinding_info_writer_); // We use Cvttsd2siq instead of Cvttsd2si due to performance reasons. The // use of Cvttsd2siq requires the movl below to avoid sign extension. __ Cvttsd2siq(result, input); @@ -1962,9 +1958,10 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( if (i.InputRegister(0) == i.OutputRegister()) { if (mode == kMode_MRI) { int32_t constant_summand = i.InputInt32(1); + DCHECK_NE(0, constant_summand); if (constant_summand > 0) { __ addl(i.OutputRegister(), Immediate(constant_summand)); - } else if (constant_summand < 0) { + } else { __ subl(i.OutputRegister(), Immediate(-constant_summand)); } } else if (mode == kMode_MR1) { @@ -2944,8 +2941,7 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) { void CodeGenerator::AssembleArchTrap(Instruction* instr, FlagsCondition condition) { - bool frame_elided = !frame_access_state()->has_frame(); - auto ool = new (zone()) WasmOutOfLineTrap(this, frame_elided, instr); + auto ool = new (zone()) WasmOutOfLineTrap(this, instr); Label* tlabel = ool->entry(); Label end; if (condition == kUnorderedEqual) { @@ -2983,6 +2979,17 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr, __ bind(&done); } +void CodeGenerator::AssembleArchBinarySearchSwitch(Instruction* instr) { + X64OperandConverter i(this, instr); + Register input = i.InputRegister(0); + std::vector<std::pair<int32_t, Label*>> cases; + for (size_t index = 2; index < instr->InputCount(); index += 2) { + cases.push_back({i.InputInt32(index + 0), GetLabel(i.InputRpo(index + 1))}); + } + AssembleArchBinarySearchSwitchRange(input, i.InputRpo(1), cases.data(), + cases.data() + cases.size()); +} + void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { X64OperandConverter i(this, instr); Register input = i.InputRegister(0); @@ -2993,7 +3000,6 @@ void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { AssembleArchJump(i.InputRpo(1)); } - void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { X64OperandConverter i(this, instr); Register input = i.InputRegister(0); @@ -3082,6 +3088,7 @@ void CodeGenerator::AssembleConstructFrame() { const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters(); if (shrink_slots > 0) { + DCHECK(frame_access_state()->has_frame()); if (info()->IsWasm() && shrink_slots > 128) { // For WebAssembly functions with big frames we have to do the stack // overflow check before we construct the frame. Otherwise we may not @@ -3093,19 +3100,18 @@ void CodeGenerator::AssembleConstructFrame() { // exception unconditionally. Thereby we can avoid the integer overflow // check in the condition code. if (shrink_slots * kPointerSize < FLAG_stack_size * 1024) { - __ Move(kScratchRegister, - ExternalReference::address_of_real_stack_limit(__ isolate())); + __ movq(kScratchRegister, + FieldOperand(kWasmInstanceRegister, + WasmInstanceObject::kRealStackLimitAddressOffset)); __ movq(kScratchRegister, Operand(kScratchRegister, 0)); __ addq(kScratchRegister, Immediate(shrink_slots * kPointerSize)); __ cmpq(rsp, kScratchRegister); __ j(above_equal, &done); } - if (!frame_access_state()->has_frame()) { - __ set_has_frame(true); - __ EnterFrame(StackFrame::WASM_COMPILED); - } + __ movp(rcx, FieldOperand(kWasmInstanceRegister, + WasmInstanceObject::kCEntryStubOffset)); __ Move(rsi, Smi::kZero); - __ CallRuntimeDelayed(zone(), Runtime::kThrowWasmStackOverflow); + __ CallRuntimeWithCEntry(Runtime::kThrowWasmStackOverflow, rcx); ReferenceMap* reference_map = new (zone()) ReferenceMap(zone()); RecordSafepoint(reference_map, Safepoint::kSimple, 0, Safepoint::kNoLazyDeopt); @@ -3272,6 +3278,23 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, break; } }; + // Helper function to write the given constant to the stack. + auto MoveConstantToSlot = [&](Operand dst, Constant src) { + if (!RelocInfo::IsWasmPtrReference(src.rmode())) { + switch (src.type()) { + case Constant::kInt32: + __ movq(dst, Immediate(src.ToInt32())); + return; + case Constant::kInt64: + __ Set(dst, src.ToInt64()); + return; + default: + break; + } + } + MoveConstantToRegister(kScratchRegister, src); + __ movq(dst, kScratchRegister); + }; // Dispatch on the source and destination operand kinds. switch (MoveType::InferMove(source, destination)) { case MoveType::kRegisterToRegister: @@ -3359,8 +3382,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, Constant src = g.ToConstant(source); Operand dst = g.ToOperand(destination); if (destination->IsStackSlot()) { - MoveConstantToRegister(kScratchRegister, src); - __ movq(dst, kScratchRegister); + MoveConstantToSlot(dst, src); } else { DCHECK(destination->IsFPStackSlot()); if (src.type() == Constant::kFloat32) { |