diff options
Diffstat (limited to 'deps/v8/src/compiler/arm/code-generator-arm.cc')
-rw-r--r-- | deps/v8/src/compiler/arm/code-generator-arm.cc | 180 |
1 files changed, 148 insertions, 32 deletions
diff --git a/deps/v8/src/compiler/arm/code-generator-arm.cc b/deps/v8/src/compiler/arm/code-generator-arm.cc index bdf4c47165..a0b502237b 100644 --- a/deps/v8/src/compiler/arm/code-generator-arm.cc +++ b/deps/v8/src/compiler/arm/code-generator-arm.cc @@ -54,6 +54,7 @@ class ArmOperandConverter final : public InstructionOperandConverter { SBit OutputSBit() const { switch (instr_->flags_mode()) { case kFlags_branch: + case kFlags_deoptimize: case kFlags_set: return SetCC; case kFlags_none: @@ -149,8 +150,11 @@ class ArmOperandConverter final : public InstructionOperandConverter { MemOperand ToMemOperand(InstructionOperand* op) const { DCHECK_NOT_NULL(op); DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot()); - FrameOffset offset = frame_access_state()->GetFrameOffset( - AllocatedOperand::cast(op)->index()); + return SlotToMemOperand(AllocatedOperand::cast(op)->index()); + } + + MemOperand SlotToMemOperand(int slot) const { + FrameOffset offset = frame_access_state()->GetFrameOffset(slot); return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset()); } }; @@ -164,7 +168,9 @@ class OutOfLineLoadFloat32 final : public OutOfLineCode { : OutOfLineCode(gen), result_(result) {} void Generate() final { - __ vmov(result_, std::numeric_limits<float>::quiet_NaN()); + // Compute sqrtf(-1.0f), which results in a quiet single-precision NaN. + __ vmov(result_, -1.0f); + __ vsqrt(result_, result_); } private: @@ -178,7 +184,9 @@ class OutOfLineLoadFloat64 final : public OutOfLineCode { : OutOfLineCode(gen), result_(result) {} void Generate() final { - __ vmov(result_, std::numeric_limits<double>::quiet_NaN(), kScratchReg); + // Compute sqrt(-1.0), which results in a quiet double-precision NaN. + __ vmov(result_, -1.0); + __ vsqrt(result_, result_); } private: @@ -222,7 +230,8 @@ class OutOfLineRecordWrite final : public OutOfLineCode { value_(value), scratch0_(scratch0), scratch1_(scratch1), - mode_(mode) {} + mode_(mode), + must_save_lr_(!gen->frame_access_state()->has_frame()) {} void Generate() final { if (mode_ > RecordWriteMode::kValueIsPointer) { @@ -236,7 +245,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { : OMIT_REMEMBERED_SET; SaveFPRegsMode const save_fp_mode = frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; - if (!frame()->needs_frame()) { + if (must_save_lr_) { // We need to save and restore lr if the frame was elided. __ Push(lr); } @@ -249,7 +258,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { __ add(scratch1_, object_, Operand(index_)); } __ CallStub(&stub); - if (!frame()->needs_frame()) { + if (must_save_lr_) { __ Pop(lr); } } @@ -262,6 +271,7 @@ class OutOfLineRecordWrite final : public OutOfLineCode { Register const scratch0_; Register const scratch1_; RecordWriteMode const mode_; + bool must_save_lr_; }; @@ -378,6 +388,11 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { DCHECK_EQ(LeaveCC, i.OutputSBit()); \ } while (0) +void CodeGenerator::AssembleDeconstructFrame() { + __ LeaveFrame(StackFrame::MANUAL); +} + +void CodeGenerator::AssembleSetupStackPointer() {} void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); @@ -394,7 +409,7 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize)); frame_access_state()->IncreaseSPDelta(-sp_slot_delta); } - if (frame()->needs_frame()) { + if (frame_access_state()->has_frame()) { if (FLAG_enable_embedded_constant_pool) { __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); } @@ -404,14 +419,39 @@ void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { frame_access_state()->SetFrameAccessToSP(); } +void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, + Register scratch1, + Register scratch2, + Register scratch3) { + DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); + Label done; + + // Check if current frame is an arguments adaptor frame. + __ ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ cmp(scratch1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); + __ b(ne, &done); + + // Load arguments count from current arguments adaptor frame (note, it + // does not include receiver). + Register caller_args_count_reg = scratch1; + __ ldr(caller_args_count_reg, + MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); + __ SmiUntag(caller_args_count_reg); + + ParameterCount callee_args_count(args_reg); + __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, + scratch3); + __ bind(&done); +} // Assembles an instruction after register allocation, producing machine code. void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ArmOperandConverter i(this, instr); - masm()->MaybeCheckConstPool(); - - switch (ArchOpcodeField::decode(instr->opcode())) { + __ MaybeCheckConstPool(); + InstructionCode opcode = instr->opcode(); + ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); + switch (arch_opcode) { case kArchCallCodeObject: { EnsureSpaceForLazyDeopt(); if (instr->InputAt(0)->IsImmediate()) { @@ -427,9 +467,15 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { frame_access_state()->ClearSPDelta(); break; } + case kArchTailCallCodeObjectFromJSFunction: case kArchTailCallCodeObject: { int stack_param_delta = i.InputInt32(instr->InputCount() - 1); AssembleDeconstructActivationRecord(stack_param_delta); + if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { + AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, + i.TempRegister(0), i.TempRegister(1), + i.TempRegister(2)); + } if (instr->InputAt(0)->IsImmediate()) { __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), RelocInfo::CODE_TARGET); @@ -458,6 +504,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { frame_access_state()->ClearSPDelta(); break; } + case kArchTailCallJSFunctionFromJSFunction: case kArchTailCallJSFunction: { Register func = i.InputRegister(0); if (FLAG_debug_code) { @@ -468,6 +515,11 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { } int stack_param_delta = i.InputInt32(instr->InputCount() - 1); AssembleDeconstructActivationRecord(stack_param_delta); + if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { + AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, + i.TempRegister(0), i.TempRegister(1), + i.TempRegister(2)); + } __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); __ Jump(ip); DCHECK_EQ(LeaveCC, i.OutputSBit()); @@ -535,7 +587,7 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { DCHECK_EQ(LeaveCC, i.OutputSBit()); break; case kArchParentFramePointer: - if (frame_access_state()->frame()->needs_frame()) { + if (frame_access_state()->has_frame()) { __ ldr(i.OutputRegister(), MemOperand(fp, 0)); } else { __ mov(i.OutputRegister(), fp); @@ -742,6 +794,67 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { __ teq(i.InputRegister(0), i.InputOperand2(1)); DCHECK_EQ(SetCC, i.OutputSBit()); break; + case kArmAddPair: + // i.InputRegister(0) ... left low word. + // i.InputRegister(1) ... left high word. + // i.InputRegister(2) ... right low word. + // i.InputRegister(3) ... right high word. + __ add(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2), + SBit::SetCC); + __ adc(i.OutputRegister(1), i.InputRegister(1), + Operand(i.InputRegister(3))); + DCHECK_EQ(LeaveCC, i.OutputSBit()); + break; + case kArmSubPair: + // i.InputRegister(0) ... left low word. + // i.InputRegister(1) ... left high word. + // i.InputRegister(2) ... right low word. + // i.InputRegister(3) ... right high word. + __ sub(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2), + SBit::SetCC); + __ sbc(i.OutputRegister(1), i.InputRegister(1), + Operand(i.InputRegister(3))); + DCHECK_EQ(LeaveCC, i.OutputSBit()); + break; + case kArmMulPair: + // i.InputRegister(0) ... left low word. + // i.InputRegister(1) ... left high word. + // i.InputRegister(2) ... right low word. + // i.InputRegister(3) ... right high word. + __ umull(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(2)); + __ mla(i.OutputRegister(1), i.InputRegister(0), i.InputRegister(3), + i.OutputRegister(1)); + __ mla(i.OutputRegister(1), i.InputRegister(2), i.InputRegister(1), + i.OutputRegister(1)); + break; + case kArmLslPair: + if (instr->InputAt(2)->IsImmediate()) { + __ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), i.InputInt32(2)); + } else { + __ LslPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), kScratchReg, i.InputRegister(2)); + } + break; + case kArmLsrPair: + if (instr->InputAt(2)->IsImmediate()) { + __ LsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), i.InputInt32(2)); + } else { + __ LsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), kScratchReg, i.InputRegister(2)); + } + break; + case kArmAsrPair: + if (instr->InputAt(2)->IsImmediate()) { + __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), i.InputInt32(2)); + } else { + __ AsrPair(i.OutputRegister(0), i.OutputRegister(1), i.InputRegister(0), + i.InputRegister(1), kScratchReg, i.InputRegister(2)); + } + break; case kArmVcmpF32: if (instr->InputAt(1)->IsDoubleRegister()) { __ VFPCompareAndSetFlags(i.InputFloat32Register(0), @@ -1155,29 +1268,32 @@ void CodeGenerator::AssembleDeoptimizerCall( int deoptimization_id, Deoptimizer::BailoutType bailout_type) { Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( isolate(), deoptimization_id, bailout_type); + // TODO(turbofan): We should be able to generate better code by sharing the + // actual final call site and just bl'ing to it here, similar to what we do + // in the lithium backend. __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); + __ CheckConstPool(false, false); } void CodeGenerator::AssemblePrologue() { CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); - if (descriptor->IsCFunctionCall()) { - if (FLAG_enable_embedded_constant_pool) { - __ Push(lr, fp, pp); - // Adjust FP to point to saved FP. - __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); + if (frame_access_state()->has_frame()) { + if (descriptor->IsCFunctionCall()) { + if (FLAG_enable_embedded_constant_pool) { + __ Push(lr, fp, pp); + // Adjust FP to point to saved FP. + __ sub(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); + } else { + __ Push(lr, fp); + __ mov(fp, sp); + } + } else if (descriptor->IsJSFunctionCall()) { + __ Prologue(this->info()->GeneratePreagedPrologue()); } else { - __ Push(lr, fp); - __ mov(fp, sp); + __ StubPrologue(info()->GetOutputStackFrameType()); } - } else if (descriptor->IsJSFunctionCall()) { - __ Prologue(this->info()->GeneratePreagedPrologue()); - } else if (frame()->needs_frame()) { - __ StubPrologue(); - } else { - frame()->SetElidedFrameSizeInSlots(0); } - frame_access_state()->SetFrameAccessToDefault(); int stack_shrink_slots = frame()->GetSpillSlotCount(); if (info()->is_osr()) { @@ -1247,15 +1363,15 @@ void CodeGenerator::AssembleReturn() { } if (descriptor->IsCFunctionCall()) { - __ LeaveFrame(StackFrame::MANUAL); - } else if (frame()->needs_frame()) { + AssembleDeconstructFrame(); + } else if (frame_access_state()->has_frame()) { // Canonicalize JSFunction return sites for now. if (return_label_.is_bound()) { __ b(&return_label_); return; } else { __ bind(&return_label_); - __ LeaveFrame(StackFrame::MANUAL); + AssembleDeconstructFrame(); } } __ Ret(pop_count); @@ -1311,9 +1427,9 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, case Constant::kHeapObject: { Handle<HeapObject> src_object = src.ToHeapObject(); Heap::RootListIndex index; - int offset; - if (IsMaterializableFromFrame(src_object, &offset)) { - __ ldr(dst, MemOperand(fp, offset)); + int slot; + if (IsMaterializableFromFrame(src_object, &slot)) { + __ ldr(dst, g.SlotToMemOperand(slot)); } else if (IsMaterializableFromRoot(src_object, &index)) { __ LoadRoot(dst, index); } else { |