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 | 325 |
1 files changed, 116 insertions, 209 deletions
diff --git a/deps/v8/src/compiler/arm/code-generator-arm.cc b/deps/v8/src/compiler/arm/code-generator-arm.cc index 1a66e5b7d4..a238cf29d4 100644 --- a/deps/v8/src/compiler/arm/code-generator-arm.cc +++ b/deps/v8/src/compiler/arm/code-generator-arm.cc @@ -152,49 +152,6 @@ class ArmOperandConverter final : public InstructionOperandConverter { namespace { -class OutOfLineLoadFloat final : public OutOfLineCode { - public: - OutOfLineLoadFloat(CodeGenerator* gen, SwVfpRegister result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { - // Compute sqrtf(-1.0f), which results in a quiet single-precision NaN. - __ vmov(result_, Float32(-1.0f)); - __ vsqrt(result_, result_); - } - - private: - SwVfpRegister const result_; -}; - -class OutOfLineLoadDouble final : public OutOfLineCode { - public: - OutOfLineLoadDouble(CodeGenerator* gen, DwVfpRegister result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { - // Compute sqrt(-1.0), which results in a quiet double-precision NaN. - __ vmov(result_, Double(-1.0)); - __ vsqrt(result_, result_); - } - - private: - DwVfpRegister const result_; -}; - - -class OutOfLineLoadInteger final : public OutOfLineCode { - public: - OutOfLineLoadInteger(CodeGenerator* gen, Register result) - : OutOfLineCode(gen), result_(result) {} - - void Generate() final { __ mov(result_, Operand::Zero()); } - - private: - Register const result_; -}; - - class OutOfLineRecordWrite final : public OutOfLineCode { public: OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, @@ -359,64 +316,6 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { } // namespace -#define ASSEMBLE_CHECKED_LOAD_FP(Type) \ - do { \ - auto result = i.Output##Type##Register(); \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto ool = new (zone()) OutOfLineLoad##Type(this, result); \ - __ b(hs, ool->entry()); \ - __ vldr(result, i.InputOffset(2)); \ - __ bind(ool->exit()); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_LOAD_INTEGER(asm_instr) \ - do { \ - auto result = i.OutputRegister(); \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto ool = new (zone()) OutOfLineLoadInteger(this, result); \ - __ b(hs, ool->entry()); \ - __ asm_instr(result, i.InputOffset(2)); \ - __ bind(ool->exit()); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_STORE_FP(Type) \ - do { \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto value = i.Input##Type##Register(2); \ - __ vstr(value, i.InputOffset(3), lo); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - -#define ASSEMBLE_CHECKED_STORE_INTEGER(asm_instr) \ - do { \ - auto offset = i.InputRegister(0); \ - if (instr->InputAt(1)->IsRegister()) { \ - __ cmp(offset, i.InputRegister(1)); \ - } else { \ - __ cmp(offset, i.InputImmediate(1)); \ - } \ - auto value = i.InputRegister(2); \ - __ asm_instr(value, i.InputOffset(3), lo); \ - DCHECK_EQ(LeaveCC, i.OutputSBit()); \ - } while (0) - #define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \ do { \ __ asm_instr(i.OutputRegister(), \ @@ -432,51 +331,51 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { __ dmb(ISH); \ } while (0) -#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr) \ - do { \ - Label exchange; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ - __ dmb(ISH); \ - __ bind(&exchange); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ store_instr(i.TempRegister(0), i.InputRegister(2), i.InputRegister(0)); \ - __ teq(i.TempRegister(0), Operand(0)); \ - __ b(ne, &exchange); \ - __ dmb(ISH); \ - } while (0) - -#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr) \ - do { \ - Label compareExchange; \ - Label exit; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ - __ dmb(ISH); \ - __ bind(&compareExchange); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ teq(i.InputRegister(2), Operand(i.OutputRegister(0))); \ - __ b(ne, &exit); \ - __ store_instr(i.TempRegister(0), i.InputRegister(3), i.InputRegister(0)); \ - __ teq(i.TempRegister(0), Operand(0)); \ - __ b(ne, &compareExchange); \ - __ bind(&exit); \ - __ dmb(ISH); \ +#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr) \ + do { \ + Label exchange; \ + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ + __ dmb(ISH); \ + __ bind(&exchange); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ store_instr(i.TempRegister(0), i.InputRegister(2), i.TempRegister(1)); \ + __ teq(i.TempRegister(0), Operand(0)); \ + __ b(ne, &exchange); \ + __ dmb(ISH); \ } while (0) -#define ASSEMBLE_ATOMIC_BINOP(load_instr, store_instr, bin_instr) \ +#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr, \ + cmp_reg) \ do { \ - Label binop; \ - __ add(i.InputRegister(0), i.InputRegister(0), i.InputRegister(1)); \ + Label compareExchange; \ + Label exit; \ __ dmb(ISH); \ - __ bind(&binop); \ - __ load_instr(i.OutputRegister(0), i.InputRegister(0)); \ - __ bin_instr(i.TempRegister(0), i.OutputRegister(0), \ - Operand(i.InputRegister(2))); \ - __ store_instr(i.TempRegister(1), i.TempRegister(0), i.InputRegister(0)); \ - __ teq(i.TempRegister(1), Operand(0)); \ - __ b(ne, &binop); \ + __ bind(&compareExchange); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ teq(cmp_reg, Operand(i.OutputRegister(0))); \ + __ b(ne, &exit); \ + __ store_instr(i.TempRegister(0), i.InputRegister(3), i.TempRegister(1)); \ + __ teq(i.TempRegister(0), Operand(0)); \ + __ b(ne, &compareExchange); \ + __ bind(&exit); \ __ dmb(ISH); \ } while (0) +#define ASSEMBLE_ATOMIC_BINOP(load_instr, store_instr, bin_instr) \ + do { \ + Label binop; \ + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ + __ dmb(ISH); \ + __ bind(&binop); \ + __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ + __ bin_instr(i.TempRegister(0), i.OutputRegister(0), \ + Operand(i.InputRegister(2))); \ + __ store_instr(i.TempRegister(2), i.TempRegister(0), i.TempRegister(1)); \ + __ teq(i.TempRegister(2), Operand(0)); \ + __ b(ne, &binop); \ + __ dmb(ISH); \ + } while (0) + #define ASSEMBLE_IEEE754_BINOP(name) \ do { \ /* TODO(bmeurer): We should really get rid of this special instruction, */ \ @@ -675,17 +574,18 @@ void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, // Check if the code object is marked for deoptimization. If it is, then it // jumps to the CompileLazyDeoptimizedCode builtin. In order to do this we need // to: -// 1. load the address of the current instruction; +// 1. compute the offset of the {CodeDataContainer} from our current location +// and load it. // 2. read from memory the word that contains that bit, which can be found in // the flags in the referenced {CodeDataContainer} object; // 3. test kMarkedForDeoptimizationBit in those flags; and // 4. if it is not zero then it jumps to the builtin. void CodeGenerator::BailoutIfDeoptimized() { int pc_offset = __ pc_offset(); - int offset = - Code::kCodeDataContainerOffset - (Code::kHeaderSize + pc_offset + 8); + int offset = Code::kCodeDataContainerOffset - + (Code::kHeaderSize + pc_offset + TurboAssembler::kPcLoadDelta); // We can use the register pc - 8 for the address of the current instruction. - __ ldr(ip, MemOperand(pc, offset)); + __ ldr_pcrel(ip, offset); __ ldr(ip, FieldMemOperand(ip, CodeDataContainer::kKindSpecificFlagsOffset)); __ tst(ip, Operand(1 << Code::kMarkedForDeoptimizationBit)); Handle<Code> code = isolate()->builtins()->builtin_handle( @@ -804,7 +704,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( // Check the function's context matches the context argument. __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); __ cmp(cp, kScratchReg); - __ Assert(eq, kWrongFunctionContext); + __ Assert(eq, AbortReason::kWrongFunctionContext); } __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeOffset)); __ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); @@ -1681,13 +1581,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kArmPush: if (instr->InputAt(0)->IsFPRegister()) { LocationOperand* op = LocationOperand::cast(instr->InputAt(0)); - if (op->representation() == MachineRepresentation::kFloat64) { - __ vpush(i.InputDoubleRegister(0)); - frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, op->representation()); - __ vpush(i.InputFloatRegister(0)); - frame_access_state()->IncreaseSPDelta(1); + switch (op->representation()) { + case MachineRepresentation::kFloat32: + __ vpush(i.InputFloatRegister(0)); + frame_access_state()->IncreaseSPDelta(1); + break; + case MachineRepresentation::kFloat64: + __ vpush(i.InputDoubleRegister(0)); + frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize); + break; + case MachineRepresentation::kSimd128: { + __ vpush(i.InputSimd128Register(0)); + frame_access_state()->IncreaseSPDelta(kSimd128Size / kPointerSize); + break; + } + default: + UNREACHABLE(); + break; } } else { __ push(i.InputRegister(0)); @@ -1701,6 +1611,24 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( DCHECK_EQ(LeaveCC, i.OutputSBit()); break; } + case kArmPeek: { + // The incoming value is 0-based, but we need a 1-based value. + int reverse_slot = i.InputInt32(0) + 1; + int offset = + FrameSlotToFPOffset(frame()->GetTotalFrameSlotCount() - reverse_slot); + if (instr->OutputAt(0)->IsFPRegister()) { + LocationOperand* op = LocationOperand::cast(instr->OutputAt(0)); + if (op->representation() == MachineRepresentation::kFloat64) { + __ vldr(i.OutputDoubleRegister(), MemOperand(fp, offset)); + } else { + DCHECK_EQ(MachineRepresentation::kFloat32, op->representation()); + __ vldr(i.OutputFloatRegister(), MemOperand(fp, offset)); + } + } else { + __ ldr(i.OutputRegister(), MemOperand(fp, offset)); + } + break; + } case kArmF32x4Splat: { int src_code = i.InputFloatRegister(0).code(); __ vdup(Neon32, i.OutputSimd128Register(), @@ -2558,47 +2486,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ ExtractLane(i.OutputRegister(), kScratchDoubleReg, NeonS8, 0); break; } - case kCheckedLoadInt8: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsb); - break; - case kCheckedLoadUint8: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrb); - break; - case kCheckedLoadInt16: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsh); - break; - case kCheckedLoadUint16: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldrh); - break; - case kCheckedLoadWord32: - ASSEMBLE_CHECKED_LOAD_INTEGER(ldr); - break; - case kCheckedLoadFloat32: - ASSEMBLE_CHECKED_LOAD_FP(Float); - break; - case kCheckedLoadFloat64: - ASSEMBLE_CHECKED_LOAD_FP(Double); - break; - case kCheckedStoreWord8: - ASSEMBLE_CHECKED_STORE_INTEGER(strb); - break; - case kCheckedStoreWord16: - ASSEMBLE_CHECKED_STORE_INTEGER(strh); - break; - case kCheckedStoreWord32: - ASSEMBLE_CHECKED_STORE_INTEGER(str); - break; - case kCheckedStoreFloat32: - ASSEMBLE_CHECKED_STORE_FP(Float); - break; - case kCheckedStoreFloat64: - ASSEMBLE_CHECKED_STORE_FP(Double); - break; - case kCheckedLoadWord64: - case kCheckedStoreWord64: - UNREACHABLE(); // currently unsupported checked int64 load/store. - break; - case kAtomicLoadInt8: ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsb); break; @@ -2642,25 +2529,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrex, strex); break; case kAtomicCompareExchangeInt8: - __ uxtb(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxtb(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, + i.TempRegister(2)); __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); break; case kAtomicCompareExchangeUint8: - __ uxtb(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxtb(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, + i.TempRegister(2)); break; case kAtomicCompareExchangeInt16: - __ uxth(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxth(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, + i.TempRegister(2)); __ sxth(i.OutputRegister(0), i.OutputRegister(0)); break; case kAtomicCompareExchangeUint16: - __ uxth(i.InputRegister(2), i.InputRegister(2)); - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + __ uxth(i.TempRegister(2), i.InputRegister(2)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, + i.TempRegister(2)); break; case kAtomicCompareExchangeWord32: - ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex); + __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); + ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex, + i.InputRegister(2)); break; #define ATOMIC_BINOP_CASE(op, inst) \ case kAtomic##op##Int8: \ @@ -2686,10 +2583,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ATOMIC_BINOP_CASE(Or, orr) ATOMIC_BINOP_CASE(Xor, eor) #undef ATOMIC_BINOP_CASE -#undef ASSEMBLE_CHECKED_LOAD_FP -#undef ASSEMBLE_CHECKED_LOAD_INTEGER -#undef ASSEMBLE_CHECKED_STORE_FP -#undef ASSEMBLE_CHECKED_STORE_INTEGER #undef ASSEMBLE_ATOMIC_LOAD_INTEGER #undef ASSEMBLE_ATOMIC_STORE_INTEGER #undef ASSEMBLE_ATOMIC_EXCHANGE_INTEGER @@ -2774,7 +2667,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr, gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, Safepoint::kNoLazyDeopt); if (FLAG_debug_code) { - __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap)); + __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromWasmTrap)); } } } @@ -2878,7 +2771,7 @@ void CodeGenerator::AssembleConstructFrame() { if (info()->is_osr()) { // TurboFan OSR-compiled functions cannot be entered directly. - __ Abort(kShouldNotDirectlyEnterOsrFunction); + __ Abort(AbortReason::kShouldNotDirectlyEnterOsrFunction); // Unoptimized code jumps directly to this entrypoint while the unoptimized // frame is still on the stack. Optimized code uses OSR values directly from @@ -2929,15 +2822,16 @@ void CodeGenerator::AssembleConstructFrame() { RecordSafepoint(reference_map, Safepoint::kSimple, 0, Safepoint::kNoLazyDeopt); if (FLAG_debug_code) { - __ stop(GetBailoutReason(kUnexpectedReturnFromThrow)); + __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromThrow)); } __ bind(&done); } } - // Skip callee-saved slots, which are pushed below. + // Skip callee-saved and return slots, which are pushed below. shrink_slots -= base::bits::CountPopulation(saves); + shrink_slots -= frame()->GetReturnSlotCount(); shrink_slots -= 2 * base::bits::CountPopulation(saves_fp); if (shrink_slots > 0) { __ sub(sp, sp, Operand(shrink_slots * kPointerSize)); @@ -2953,16 +2847,29 @@ void CodeGenerator::AssembleConstructFrame() { __ vstm(db_w, sp, DwVfpRegister::from_code(first), DwVfpRegister::from_code(last)); } + if (saves != 0) { // Save callee-saved registers. __ stm(db_w, sp, saves); } + + const int returns = frame()->GetReturnSlotCount(); + if (returns != 0) { + // Create space for returns. + __ sub(sp, sp, Operand(returns * kPointerSize)); + } } void CodeGenerator::AssembleReturn(InstructionOperand* pop) { CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); int pop_count = static_cast<int>(descriptor->StackParameterCount()); + const int returns = frame()->GetReturnSlotCount(); + if (returns != 0) { + // Free space of returns. + __ add(sp, sp, Operand(returns * kPointerSize)); + } + // Restore registers. const RegList saves = descriptor->CalleeSavedRegisters(); if (saves != 0) { |